2010-11-08 56 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