Я пытаюсь реализовать эту модель с помощью 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
Пожалуйста, дайте мне знать, если мне нужно добавить дополнительную информацию, чтобы сделать вопрос более ясным.
hi @Joe Enzminger, можете ли вы подробно рассказать, что является самым простым способом переопределить метод getter, предоставленный код не является полным, и я нахожу некоторые проблемы, понимающие, что вы делаете на каждом шаге. Спасибо – Hilmi
Посмотрите на [this] (https://gist.github.com/joeenzminger/7526426) фрагмент кода. –
Спасибо большое @Joe Enzminger. – Hilmi