Hallo!
Ich habe eine generische Methode, der ein Typ (MyClass) übergeben werden muss.
Allerdings steckt der Typ in einer DLL die dynamisch per Reflection angezogen werden muss.
// Generische Methode
Create<T>()
// DLL anziehen
Assembly optionaleDLL = Assembly.LoadFrom("MyDLL.dll");
Type optionalType = optionaleDLL.GetType("Namespace.MyClass");
Jetzt versuche ich der Generischen Methode den Typen zu übergeben:
Create<optionalType>()
Warum funktioniert das nicht? Oder geht das anders?
Ich bekomme immer eine Exception:
The type or namespace name 'optionalType' could not be found (are you missing a using directive or an assembly reference?)
Hallo husky410,
Generics sind eine Compilezeit-Angelegenheit. Den Typ kann man nicht zur Laufzeit übergeben. No chance!
Du könntest höchstens zu Laufzeit Code erzeugen und diesen dann mit Microsoft.CSharp.CSharpCodeProvider oder System.CodeDom.Compiler.ICodeCompiler zur Laufzeit übersetzen.
Wenn es dir nur um die Erzeugung von Objekten des Typs T geht, dann benutze Activator.CreateInstance.
herbivore
Hi herbivore!
Leider geht es mir nicht nur um die Erzeugung von Objekten...
Aber die Idee zur Laufzeit Code zu erzeugen könnte gehen.
Schönen Dank!
Original von herbivore
Hallo husky410,Generics sind eine Compilezeit-Angelegenheit. Den Typ kann man nicht zur Laufzeit übergeben. No chance! Es gibt immer noch Reflection. 😉
Einmal in ein nicht generisches Delegate verpackt, kann man auch generische Methoden problemlos aufrufen.
// wie auch immer huskys Create-Methode aussieht
public static T Create<T>()
where T : new()
{
Console.WriteLine("Creating instance of type {0}...", typeof(T));
return new T();
}
public delegate object CreateMethod();
static CreateMethod WrapCreate<T>()
where T : new()
{
return delegate
{
return Create<T>();
};
}
public static CreateMethod Wrap(Type type)
{
MethodInfo m = typeof(Program).GetMethod("WrapCreate",
BindingFlags.Static | BindingFlags.NonPublic);
m = m.MakeGenericMethod(type);
return m.Invoke(null, null) as CreateMethod;
}
static void Main(string[] args)
{
Type optionalType = Type.GetType("Namespace.MyClass, MyDLL");
CreateMethod create = Wrap(optionalType);
for (int i = 0; i < 10; i++)
{
object instance = create();
}
}
Du könntest höchstens zu Laufzeit Code erzeugen und diesen dann mit Microsoft.CSharp.CSharpCodeProvider oder System.CodeDom.Compiler.ICodeCompiler zur Laufzeit übersetzen. Aua! Wenn man dynamisch IL code geniert, dann sollte man IL Code generieren. Einen CodeDom zur Laufzeit zu benutzen nur um etwas ausführen zu können ist absolut übertrieben und ineffizient.
DynamicMethod oder AppDomain.DefineDynamicAssembly kann man benutzen, je nachdem ob man nur eine Methode oder ganze Typen generieren will.
Wenn es dir nur um die Erzeugung von Objekten des Typs T geht, dann benutze Activator.CreateInstance. Würde ich hier auch vorschlagen, außer man will die Factory öfter aufrufen. (Activator ist verflucht langsam)
Die andere Lösung besteht darin, statt des konkreten Typen mit einem Interface zu arbeiten. Der ist ja zur Compile-Zeit bekannt und kann zur Laufzeit durch das Plugin "ausgefüllt" werden. Eigentlich die übliche Vorgehensweise in diesem Fall.
@svenson
Ich denke spätestens wenn er mit der erzeugten Instanz arbeiten will, wäre die Frage gekommen. g
Mir ging's nur darum eine Lösung zu zeigen, wie man auch ohne dynamischen Code (also auch ohne spezielle Berechtigungen) eine generische Methode so verpacken kann, dass man sie ohne Typenparameter wiederholt aufrufen kann.