2010-11-08 98 views
0

我需要在运行时创建具有属性的类型。 类型必须是这个样子:在运行时生成类型

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

但是当我试图值设置为属性,异常呼吁onAfterPropertySetthis参数之前抛出

+0

什么你想完成?生成IL很少是最好的解决方案。 – SLaks 2010-11-08 21:33:34

+0

你会得到什么例外? – SLaks 2010-11-08 21:34:13

+0

我得到TargetInvocationException – Timur 2010-11-08 21:36:44

回答

1

你并不真正接近。您忘了平等测试并将此参数的隐藏传递给实例方法。要做到这一点,最好的办法是先用C#代码:

class Test { 
    private string _field1; 
    private void OnAfterPropertySet(string arg) { } 
    public string Property1 { 
     set { 
      if (_field1 != value) { 
       _field1 = value; 
       OnAfterPropertySet("Property1"); 
      } 
     } 
    } 
} 

建立它在发行模式,然后看看生成的IL与程序Ildasm.exe或反思:

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 
0

你需要Ldarg_0