私は動的ラッパーを作成しようとしていますが、私の間違いを忘れることはありません。ここで は、私が得たものである:IL Emit - プロパティのリダイレクト
単純なデータクラス:
public class Data
{
public int MyProperty { get; set; } = 42;
}
基本クラス、リダイレクトのための場を提供する:
public class WrapperBase<T> where T : new() { public WrapperBase() { Field = new T(); } public T Field { get; set; } public void Foo(); }
リダイレクトベースを使用してクラス:
public class SomeDynamicClass : WrapperBase<Data> { }
と、それを使用してクラス:
public class User
{
public User()
{
Content = MyFactory.Create<SomeDynamicClass>();
}
public object Content { get; set; }
}
これは私が工場を作成したいものです。
public class DesiredResult : SomeDynamicClass
{
public int MyProperty
{
get { return Field.MyProperty; }
set
{
Field.MyProperty = value;
Foo();
}
}
}
私はILコードをチェックし、それを再コーディングしようとしたが、私のミスがありました見つけることができません。ここで私はこれまで得たものである:私は無効なILコードを生成していますように
public class Factory
{
private const String NAMESPACE = "vmproxy.{0}";
public object Create<T>() where T : class
{
AssemblyName an = new AssemblyName();
an.Name = Guid.NewGuid().ToString();
AppDomain ad = AppDomain.CurrentDomain;
AssemblyBuilder ab = ad.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
var _mb = ab.DefineDynamicModule(an.Name);
var fieldProp = typeof(T).GetProperty("Field");
var modelType = typeof(T).GetProperty("Field").PropertyType;
var name = typeof(T).Name;
var tb = _mb.DefineType(String.Format(NAMESPACE, name), TypeAttributes.Public | TypeAttributes.Class, typeof(T));
foreach (var property in modelType.GetProperties())
{
PropertyBuilder prop = tb.DefineProperty(property.Name, PropertyAttributes.None, property.PropertyType, null);
MethodBuilder meth = tb.DefineMethod("get_" + property.Name,
MethodAttributes.Public |
MethodAttributes.SpecialName |
MethodAttributes.Virtual |
MethodAttributes.HideBySig,
property.PropertyType, Type.EmptyTypes);
ILGenerator ilGen = meth.GetILGenerator();
Label endOfMethod = ilGen.DefineLabel();
ilGen.Emit(OpCodes.Ldarg_0);
//ilGen.Emit(OpCodes.Call, fieldProp.GetGetMethod());
ilGen.EmitCall(OpCodes.Call, fieldProp.GetGetMethod(), null);
//ilGen.Emit(OpCodes.Callvirt, property.GetGetMethod());
ilGen.EmitCall(OpCodes.Callvirt, property.GetGetMethod(),null);
ilGen.Emit(OpCodes.Stloc_0);
ilGen.Emit(OpCodes.Br_S, endOfMethod);
ilGen.MarkLabel(endOfMethod);
ilGen.Emit(OpCodes.Ldloc_0);
ilGen.Emit(OpCodes.Ret);
prop.SetGetMethod(meth);
//meth = tb.DefineMethod("set_" + property.Name,
// MethodAttributes.Public |
// MethodAttributes.SpecialName |
// MethodAttributes.Virtual |
// MethodAttributes.HideBySig,
// null, new Type[] { property.PropertyType });
//ilGen = meth.GetILGenerator();
//ilGen.Emit(OpCodes.Ldarg_0);
//TBD...
break;
}
return Activator.CreateInstance(tb.CreateType());
}
は思え...作成されたILコードをチェックする方法はあり...
編集:?IL私が作成しようとしていますコード:
.method public hidebysig specialname instance int32
get_IntProp() cil managed
{
// Code size 17 (0x11)
.maxstack 1
.locals init ([0] int32 V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: call instance !0 class FactoryWrapper.WrapperBase`1<class FactoryWrapper.Data>::get_Field()
IL_0007: callvirt instance int32 FactoryWrapper.Data::get_IntProp()
IL_000c: stloc.0
IL_000d: br.s IL_000f
IL_000f: ldloc.0
IL_0010: ret
} // end of method DerivedClass3::get_IntProp
.method public hidebysig specialname instance void
set_IntProp(int32 'value') cil managed
{
// Code size 27 (0x1b)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: call instance !0 class FactoryWrapper.WrapperBase`1<class FactoryWrapper.Data1::get_Field()
IL_0007: ldarg.1
IL_0008: callvirt instance void FactoryWrapper.Data::set_IntProp(int32)
IL_000d: nop
IL_000e: ldarg.0
IL_0014: callvirt instance void class FactoryWrapper.WrapperBase`1<class FactoryWrapper.Data1>::Foo()
IL_0019: nop
IL_001a: ret
} // end of method DerivedClass3::set_IntProp
編集:は
"オフセット0x000cで 不明なローカルvariablenumber" を受信します私はアイデアを得た後は
ILを確認するためにどのツールを使用していますか?もし私があなただったら私はILDASMを使います。あなたがビジュアルスタジオを持っているなら、ボーナスは既にあなたのシステムにあります。 – Botonomous
'AssemblyBuilderAccess.RunAndSave'を使用して、あなたのアセンブリを保存してからPEVerifyを実行したり、逆アセンブルしたりして、間違っていることを確認してください。 (明らかに、実稼働環境にデプロイする際に節約ビットをスタブすることはできますが、デバッグ段階では非常に重要です)。 –
もちろん、私は生成されたassemlbyを保存しようとするとILdasm ... – Jaster