Hi,
ich probiere gerade einen einfach Getter mit IL-code in c# nachzubauen:
public class Test1
{
public IList test1
{
get
{
return Manager.Load(typeof(Test1), "testsa", this);
}
}
}
public class Manager
{
public static IList Load(Type typeA, string name, object oA)
{
Console.WriteLine("Load(" + typeA + ", " + name + "," + oA + ")");
return null;
}
}
so sieht das ganze nun in C# aus.
Ich möchte aber jetzt die test1-Methode dynamisch mit IL generieren. Natürlich hab ich mir das ganze mit ildasm als IL geholt.
Sieht dann so aus:
.method public hidebysig specialname instance class [mscorlib]System.Collections.IList
get_test1() cil managed
{
// Code size 27 (0x1b)
.maxstack 3
.locals init ([0] class [mscorlib]System.Collections.IList CS$1$0000)
IL_0000: nop
IL_0001: ldtoken ConsoleApplication1.Test1
IL_0006: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_000b: ldstr "testsa"
IL_0010: ldarg.0
IL_0011: call class [mscorlib]System.Collections.IList Manager::Load(class [mscorlib]System.Type,
string,
object)
IL_0016: stloc.0
IL_0017: br.s IL_0019
IL_0019: ldloc.0
IL_001a: ret
} // end of method Test1::get_test1
Natürlich hab ich das dann in C# nachgebaut:
ILGenerator ilGenerator = methodBuilder.GetILGenerator();
Type myType = typeof(String);
string myString = "testString";
Label endOfMethod = ilGenerator.DefineLabel();
ilGenerator.Emit(OpCodes.Nop);
ilGenerator.Emit(OpCodes.Ldtoken, myType);
ilGenerator.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"));
ilGenerator.Emit(OpCodes.Ldstr, myString);
ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Call, typeof(Manager).GetMethod("Load", new Type[] {typeof(Type), typeof(string), typeof(object)}));
ilGenerator.Emit(OpCodes.Stloc_0);
ilGenerator.Emit(OpCodes.Br_S, endOfMethod);
ilGenerator.MarkLabel(endOfMethod);
ilGenerator.Emit(OpCodes.Ldloc_0);
ilGenerator.Emit(OpCodes.Ret);
Beim Ausführen tritt folgende Exception auf:
System.InvalidProgramException: Invalid IL code in TestType:get_test1 (): IL_0016: stloc.0
Habt ihr eine Idee warum das nicht funktioniert? Bin gerade erst dabei mich in IL einzuarbeiten aber ich versteh nicht warum das nicht geht:/
danke.
dazu noch der MethodBuilder:
MethodBuilder methodBuilder =
typeBuilder.DefineMethod("get_test1", MethodAttributes.Public, typeof(IList), new Type[] {});
Ich will hier die Methode nicht überschreiben, ich generiere meinen eigenen Type 😃
überschreiben kannst du die Methode sowieso nicht, nur mal zur Info (wollte das auch mal machen um mir den Overhead bei INotifyPropertyChanged-Properties zu entfernen .. und hab rausgefunden dass das halt net geht). Wirklich helfen kann ich dir bei deinem problem jetzt auch nicht, bin nicht gerade der Fan von IL.
Aber hier ist eine Seite die mir weitergeholfen hat bei meinen ersten Versuchen http://www.albahari.com/nutshell/ch17.aspx
Was dir auch noch weiterhelfen könnte wäre folgender Link: http://www.codeproject.com/KB/cs/fast_dynamic_properties.aspx
Träume nicht dein Leben sondern lebe deinen Traum.
Viele Grüße, David Teck
Hallo Zoigl,
ich habe mir nicht alles angeschaut, denn schon in der zweiten Emit-Zeile gibt es Unterschiede im Typ (ConsoleApplication1.Test1 vs String). Oder ist das eine absichtliche Abweichung? Du solltest nochmal alles Schritt für Schritt durchgehen.
herbivore
den Type und den String will ich dynamisch hinzufügen, deswegen ist es im Beispiel ein String und im anderen Test1 😃
Hallo Zoigl,
Bin gerade erst dabei mich in IL einzuarbeiten aber ich versteh nicht warum das nicht geht:/
guck dir mal das Reflector-Addin ReflectionEmitLanguage an.
Gruß,
dN!3L