Генерация типа во время выполнения - PullRequest
0 голосов
/ 09 ноября 2010

Мне нужно создать тип со свойствами во время выполнения.Тип должен выглядеть так:

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 ]

1 голос
/ 09 ноября 2010

Ты не совсем близко. Вы забыли тест на равенство и передали скрытый аргумент this в метод экземпляра. Лучший способ сделать это - сначала написать код на C #:

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

Постройте его в режиме Release, затем посмотрите на сгенерированный IL с помощью ildasm.exe или 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
0 голосов
/ 09 ноября 2010

Вам нужно Ldarg_0 перед вызовом onAfterPropertySet для параметра this.

...