Я пытаюсь написать некоторый .NET-код, который динамически генерирует различные типы из списка простых интерфейсов, содержащих только средства определения свойств/геттеры. Один из типов, которые я хотел бы генерировать из списка, - это тот, который поддерживает данные интерфейсы (с автоматически генерируемыми полями поддержки), но также отслеживает все операции набора свойств, записывая, какие свойства были изменены (и в будущем, возможно, время, контекст, пользователь и т. д., которые внесли изменения). После создания образцов в C# и изучения их с помощью ILDASM, у меня есть работа, но есть одна часть кода, для которой IL выглядит намного сложнее, чем должно быть. Для этого типа внутри кода, который определяет установщик для свойства, я устанавливаю значение в поле (достаточно просто), но тогда мне нужно получить PropertyInfo
для свойства, которое я устанавливаю (так что позже пользователь может перечислить PropertyInfo
s для свойств, которые были изменены). Для того, чтобы получить PropertyInfo
для свойства которого сеттер я нахожусь в середине определения, у меня есть следующий код (средняя секция):C# Получение PropertyInfo в setter с помощью PropertyBuilder
...
PropertyBuilder pb = tb.DefineProperty(property.Name, property.Attributes, property.PropertyType, null);
MethodAttributes attr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Virtual;
MethodBuilder setmb = tb.DefineMethod(SetPropertyMethodPrefix + property.Name, attr, null, new Type[] { property.PropertyType });
ILGenerator setgen = setmb.GetILGenerator();
...
// store the value in the backing field
setgen.Emit(OpCodes.Ldarg_0);
setgen.Emit(OpCodes.Ldarg_1);
setgen.Emit(OpCodes.Stfld, fb);
// get ready to give the change tracker the PropertyInfo for this property
setgen.Emit(OpCodes.Ldarg_0);
setgen.Emit(OpCodes.Ldfld, changeTrackerField);
// get the PropertyInfo for this property (there has to be a better way!)
setgen.Emit(OpCodes.Ldarg_0);
setgen.Emit(OpCodes.Call, typeof(object).GetMethod("GetType"));
// alternatively, instead of the two lines above, I can get the type token directly and get the type from there, which may or may not be any faster...
// setgen.Emit(OpCodes.Ldtoken, tb.TypeToken.Token);
// setgen.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", new Type[] { typeof(RuntimeTypeHandle) }));
setgen.Emit(OpCodes.Ldstr, property.Name);
setgen.Emit(OpCodes.Callvirt, typeof(Type).GetMethod("GetProperty", new Type[] { typeof(string) }));
// give the PropertyInfo to our change tracking object
setgen.Emit(OpCodes.Callvirt, typeof(ChangeTracker).GetMethod("MarkPropertyChanged"));
setgen.Emit(OpCodes.Ret);
В средней части эквивалентна кода C#: GetType().GetProperty(<propertyName>)
, но кажется, что должен быть какой-то более быстрый способ получить PropertyInfo
за собственность, которую я нахожу посреди здания. Версия GetTypeFromHandle
кажется, что она может быть более эффективной (typeof (T) vs. this.GetType()), но я предполагаю, что есть способ обойти GetProperty
вообще, возможно, используя PropertyBuilder.PropertyToken
.
Есть ли способ получить экземпляр PropertyInfo
для объекта? Я нахожусь посередине здания, не прибегая к вставке кода IL, который делает саморефлексию?
Я не понимаю, почему вы не используете стандартные методы отражения и пытаетесь написать код на основе сгенерированного кода IL. Сказав это, отражение дает вам гибкость, но оно имеет более низкую производительность. Кроме того, IObservable - очень хороший встроенный трекер изменений. – Sparrow
IObservable - очень хороший трекер изменений **, если вы работаете в том же процессе **. В этом случае я хочу иметь возможность запускать удаленно. – James
Достаточно честный. Вы используете дженерики?Вы можете написать что-то вроде этого (что, как я считаю, не имеет лучшей производительности): var props = typeof (T) .GetProperties(); – Sparrow