开发者

Generating type at runtime

I need to create type with properties at runtime. Type must be look like this:

public class RunTimeType : BaseType
{

private string _field1;

public string Property1
  {

     get { return _field1; }
     set
     {
        if (_field1 != value)
        {
           _field1 = value;
           OnAfterPropertySet("Property1");
        }
     }
  } 

}

the question is how to create Set method 开发者_JAVA百科? Now i use folowing code :

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

but when i trying to set value to the property, exception is thrown


You're not really close. You forgot the equality test and passing the hidden this argument to the instance method. The best way to do this is to write the code in C# first:

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

Build it in the Release mode then take a look at the generated IL with ildasm.exe or Reflector:

  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


You need to Ldarg_0 before calling onAfterPropertySet for the this parameter.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜