Frage

Ist es möglich, ein Objekt mit seinem internen Konstruktor innerhalb einer generischen Methode zu konstruieren?

public abstract class FooBase { }

public class Foo : FooBase {
   internal Foo() { }
}

public static class FooFactory {
    public static TFooResult CreateFoo<TFooResult>()
    where TFooResult : FooBase, new() {
        return new TFooResult();
    }
}

FooFactory liegt in der gleichen Anordnung wie Foo. Klassen rufen Sie die Factory-Methode wie folgt aus:

var foo = FooFactory.CreateFoo<Foo>();

Sie die Kompilierung-Fehler:

  

‚Foo‘ muss einen nicht-abstrakten Typ mit einem öffentlichen parameterlosen Konstruktor sein, um es zu benutzen als Parameter ‚TFooType‘ in der generischen Art oder Methode 'FooFactory.CreateFoo ()

Gibt es eine Möglichkeit, dies zu umgehen?

Ich habe auch versucht:

Activator.CreateInstance<TFooResult>(); 

Dies wirft die gleichen Fehler zur Laufzeit.

War es hilfreich?

Lösung

Sie könnten die new() Einschränkung und Rückkehr entfernen:

//uses overload with non-public set to true
(TFooResult) Activator.CreateInstance(typeof(TFooResult), true); 

obwohl der Kunde das auch tun könnte. Dies ist jedoch anfällig für Laufzeitfehler.

Dies ist ein schwieriges Problem in einer sicheren Weise zu lösen, da die Sprache nicht eine abstrakte Konstruktor declaraton zulässt.

Andere Tipps

  

Das Argument Typ muss eine haben    Öffentlichkeit parameterlosen Konstruktor. Bei der Verwendung zusammen mit anderen   Einschränkungen, die neue () constraint must   angegeben werden zuletzt.

http://msdn.microsoft.com/en-us/library /d5x73970.aspx

edit: also nein, wenn Sie neu () Einschränkung verwenden, können Sie nicht, dass die Klasse übergeben, wenn Sie neue nicht-Einschränkung () verwenden Sie versuchen, mithilfe von Reflektion können neue Instanz erstellen

public static TFooResult CreateFoo<TFooResult>()
where TFooResult : FooBase//, new()
        {
            return (TFooResult)typeof(TFooResult).GetConstructor(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance, null, new Type[] {}, null).Invoke(new object[]{});
            //return new TFooResult();
        }

Es kann einige Workarounds wie unten, aber ich glaube nicht, dass du so gehen wollen!

  • Setzen Sie switch-Anweisung innerhalb der Fabrik dass die Instanz erstellen basierend nach Art der Typ-Parameter.

  • Jede konkrete Umsetzung FooBase wird registrieren FooFactory die Fabrik-Methode übergeben es selbst zu schaffen. So FooFactory das interne Wörterbuch verwenden

  • Die Ausweitung auf der analogen Leitung außer Zuordnung zwischen Typ-Parametern und den konkreten Umsetzung wäre externer Code (xml-Datei, Konfiguration usw.). IOC / DI-Container kann auch hier helfen.

public class GenericFactory
{
    public static T Create<T>(object[] args)
    {
        var types = new Type[args.Length];
        for (var i = 0; i < args.Length; i++)
            types[i] = args[i].GetType();

        return (T)typeof(T).GetConstructor(types).Invoke(args);
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top