在运行时生成类型

时间:2010-11-08 21:28:15

标签: c#-4.0 il

我需要在运行时创建带属性的类型。 类型必须如下所示:

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

但是当我尝试为属性设置值时,抛出异常

2 个答案:

答案 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