nope, MetaClasses sind kein Teil der CLR. Somit gibt's die auch nicht in C#.
Wenn es dir nur darum geht Instanzen zu erzeugen wäre dass hier möglich:
C#-Quelltext
1: 2: 3: 4: 5:
| T CreateInstance<T>() where T : new() { return new T(); } |
Man beachte die new() -constraint, welche für T einen öffentlichen, parameterlosen Contructor vorschreibt.
Willst du dem Constructor Parameter übergeben hast du die Qual der Wahl...
Es gibt da die Klasse Activator. Die it einfach zu benutzen, aber muss für jeden Call den richtigen Constructor finde -> laaaahmarschig
Du kannst dir eine generische Factory bauen, die den nötigen Il Code für einen call auf den richtigen Constructor generiert.
Da generische Klassen für jeden unterchiedlichen Typparameter einen eigenen Satz von statischen Variablen haben, ist es sehr easy den genierten Code immer wieder benutzen zu können.
Da ich gerne mit Dynamic Methods spiele, habe ich dir mal ein kleines Beispiel gebaut.
Die Methode zum Generieren des constructor Wrappers habe ich absichtlich unabhängig von Parameteranzahl und -typ gemacht, so kannst du sie einfach selbst benutzen.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46:
| static class Factory<T> { public static T CreateInstance(int someValue) { return constructor(someValue); }
delegate T Constructor(int someValue);
static Constructor constructor = InitialConstructor;
static T InitialConstructor(int someValue) { constructor = CreateConstructorCall(new Type[] { typeof(int) });
return constructor(someValue); }
static Constructor CreateConstructorCall(Type[] parameterTypes) { DynamicMethod method = new DynamicMethod("ConstructorCall", typeof(T), parameterTypes, typeof(Factory<T>));
ILGenerator codeGen = method.GetILGenerator();
for (byte argument = 0; argument < parameterTypes.Length; argument++) { codeGen.Emit(OpCodes.Ldarg_S, argument); }
codeGen.Emit(OpCodes.Newobj, typeof(T).GetConstructor(parameterTypes)); codeGen.Emit(OpCodes.Ret);
return (Constructor)method.CreateDelegate(typeof(Constructor)); } } |
Dynamic methods laufen unter "light weight code generations". D.h. der Code sollte im einstelligen ms-Bereich generiert werden.
Jeder weitere Call ist vergleichbar mit einem normal kompilierten statischen Methodenaufruf, auf deutsch: sackschnell.
Hier noch ein bisschech Beispiel code, der zeigen soll wie und das es funktioniert.
Das Interface war nicht notwendig, aber dadurch muste ich die Test methode nur einmal schreiben.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51:
| interface ISomeValue { int SomeValue { get;} }
struct Struct : ISomeValue { int someValue;
public int SomeValue { get { return someValue; } }
public Struct(int someValue) { this.someValue = someValue; } }
class Class : ISomeValue { int someValue;
public int SomeValue { get { return someValue; } }
public Class(int someValue) { this.someValue = someValue; } }
class Program { static void Main(string[] args) { Test<Class>(1); Test<Struct>(2); }
static void Test<T>(int someValue) where T : ISomeValue { T test = Factory<T>.CreateInstance(someValue);
Console.WriteLine("{0}: {1}", test, test.SomeValue); } } |
Bei Fragen einfach fragen...