我需要在运行时创建带属性的类型。 类型必须如下所示:
public class RunTimeType : BaseType
{
private string _field1;
public string Property1
{
get { return _field1; }
set
{
if (_field1 != value)
{
_field1 = value;
OnAfterPropertySet("Property1");
}
}
}
}
问题是如何创建Set方法?现在我使用以下代码:
var propertyName = "Property1";
var onAfterPropertySet = baseType.GetMethod("OnAfterPropertySet",
BindingFlags.Instance | BindingFlags.InvokeMethod |
BindingFlags.NonPublic, null, new[] { typeof(string) },
null);
ILGenerator currSetIL = currSetPropMthdBldr.GetILGenerator();
currSetIL.Emit(OpCodes.Ldarg_0);
currSetIL.Emit(OpCodes.Ldarg_1);
currSetIL.Emit(OpCodes.Stfld, field);
currSetIL.Emit(OpCodes.Ldstr, propertyName);
currSetIL.Emit(OpCodes.Call, onAfterPropertySet);
currSetIL.Emit(OpCodes.Pop);
currSetIL.Emit(OpCodes.Ret);
但是当我尝试为属性设置值时,抛出异常
答案 0 :(得分:1)
你并不是很亲密。您忘记了相等测试并将隐藏的 this 参数传递给实例方法。执行此操作的最佳方法是首先使用C#编写代码:
class Test {
private string _field1;
private void OnAfterPropertySet(string arg) { }
public string Property1 {
set {
if (_field1 != value) {
_field1 = value;
OnAfterPropertySet("Property1");
}
}
}
}
在Release模式下构建它,然后使用ildasm.exe或Reflector查看生成的IL:
IL_0000: ldarg.0
IL_0001: ldfld string ConsoleApplication1.Test::_field1
IL_0006: ldarg.1
IL_0007: call bool [mscorlib]System.String::op_Inequality(string,
string)
IL_000c: brfalse.s IL_0020
IL_000e: ldarg.0
IL_000f: ldarg.1
IL_0010: stfld string ConsoleApplication1.Test::_field1
IL_0015: ldarg.0
IL_0016: ldstr "Property1"
IL_001b: call instance void ConsoleApplication1.Test::OnAfterPropertySet(string)
IL_0020: ret
答案 1 :(得分:0)
在为Ldarg_0
参数调用onAfterPropertySet
之前,您需要this
。