2012-01-03 2 views
2

Я пытаюсь реализовать эту модель с помощью Reflection.Emit (TypeBuilder):Переопределение определения собственности с Reflection.Emit

public class ClassToBeProxied 
{ 
    public virtual object Property1 { get; set; } 
} 

public class Proxy : ClassToBeProxied 
{ 
    [AttributeToBeAdded] 
    public override object Property1 
    { 
     get 
     { 
      //do something else to return the object - i.e get it from the database 
      return null; //stub 
     } 
     set 
     { 
      //do something else to set the object - i.e, save it to a database 
     } 
    }   
} 

Если все, что я делал было перехватывать получить и установить методы, то это работает:

PropertyInfo info = typeof(ClassToBeProxied).GetProperty("Property1", BindingFlags.Public | BindingFlags.Instance); 
{ 
    MethodBuilder pGet = typeBuilder.DefineMethod("get_" + info.Name, MethodAttributes.Virtual | MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, info.PropertyType, Type.EmptyTypes); 
    ILGenerator pILGet = pGet.GetILGenerator(); 

    //The proxy object 
    pILGet.Emit(OpCodes.Ldarg_0); 
    //The database 
    pILGet.Emit(OpCodes.Ldfld, database); 
    //The proxy object 
    pILGet.Emit(OpCodes.Ldarg_0); 
    //The ObjectId to look for 
    pILGet.Emit(OpCodes.Ldfld, f); 
    pILGet.Emit(OpCodes.Callvirt, typeof(MongoDatabase).GetMethod("Find", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(ObjectId) }, null).MakeGenericMethod(info.PropertyType)); 
    pILGet.Emit(OpCodes.Ret); 

    MethodBuilder pSet = typeBuilder.DefineMethod("set_" + info.Name, MethodAttributes.Virtual | MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, null, new Type[] { info.PropertyType }); 
    ILGenerator pILSet = pSet.GetILGenerator(); 
    pILSet.Emit(OpCodes.Ldarg_0); 
    pILSet.Emit(OpCodes.Ldarg_1); 
    pILSet.Emit(OpCodes.Ldarg_0); 
    pILSet.Emit(OpCodes.Ldfld, database); 
    pILSet.Emit(OpCodes.Call, typeof(ProxyBuilder).GetMethod("SetValueHelper", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(object), typeof(MongoDatabase) }, null)); 
    pILSet.Emit(OpCodes.Stfld, f); 
    pILSet.Emit(OpCodes.Ret); 

    //Edit: Added fix 
    newProp.SetSetMethod(pSet); 
    newProp.SetGetMethod(pGet); 
} 

Но что мне нужно сделать, это также добавить атрибут свойства. Я не могу понять, как это сделать.

Если добавить новый PropertyDefinition:

PropertyBuilder newProp = typeBuilder.DefineProperty(info.Name, PropertyAttributes.None, info.PropertyType, Type.EmptyTypes); 
newProp.SetCustomAttribute(new CustomAttributeBuilder(typeof(AttributeToBeAdded).GetConstructor(Type.EmptyTypes), Type.EmptyTypes, new FieldInfo[0], new object[0])); 

, а затем вызвать GetProperties() на сгенерированной типа, два свойства с тем же именем появляются. Однако, если я создам код вручную (как в примере выше) и вызывается typeof (Proxy) .GetProperties(), то отображается только одно свойство (свойство производного класса). Это поведение, которое мне нужно, но я не могу попасть туда с Reflection.Emit

Пожалуйста, дайте мне знать, если мне нужно добавить дополнительную информацию, чтобы сделать вопрос более ясным.

+0

hi @Joe Enzminger, можете ли вы подробно рассказать, что является самым простым способом переопределить метод getter, предоставленный код не является полным, и я нахожу некоторые проблемы, понимающие, что вы делаете на каждом шаге. Спасибо – Hilmi

+0

Посмотрите на [this] (https://gist.github.com/joeenzminger/7526426) фрагмент кода. –

+0

Спасибо большое @Joe Enzminger. – Hilmi

ответ