Laden...

Probleme mit Reflection

Erstellt von husky410 vor 17 Jahren Letzter Beitrag vor 17 Jahren 2.028 Views
husky410 Themenstarter:in
225 Beiträge seit 2005
vor 17 Jahren
Probleme mit Reflection

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?)

49.485 Beiträge seit 2005
vor 17 Jahren

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

husky410 Themenstarter:in
225 Beiträge seit 2005
vor 17 Jahren

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!

347 Beiträge seit 2006
vor 17 Jahren

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)

S
8.746 Beiträge seit 2005
vor 17 Jahren

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.

347 Beiträge seit 2006
vor 17 Jahren

@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.