Используя C # /. Net 4.0, я храню данные в BindingList, где dataRow определяется во время выполнения через Reflection.Emit.(Структура входящих данных различается и определяется внешним источником.) После небольшого испытания моего первого набега в мир отражений и IL я смог создать свой dataRow, заполнить его значениями, заполнить мой BindingList иотобразить результат в сетке.Теперь я пытаюсь реализовать интерфейс INotifyPropertyChanged и PropertyChangedEventHandler, когда в данные вносятся изменения.Используя this в качестве руководства, у меня есть код, который запускается, но не похоже, что событие RaisePropertyChanged запускается или просто ничего не делает.Когда я сравниваю свою динамическую версию с обычной / статической версией с помощью ildasm.exe, я вижу значительные различия в методах remove_PropertyChanged и add_PropertyChanged.Может ли кто-нибудь предоставить некоторые советы или примеры реализации интерфейса INotifyPropertyChanged с помощью отражения.
После дальнейшего рассмотрения кажется, что поле события должно быть нулевым, поэтому PropertyChangedEventHandler не вызывается.Я добавил несколько окон сообщений в конструктор метода RaiseProprtyChanged и обнаружил, что эквивалент if (PropertyChanged! = Null) возвращает ноль / ложь, поэтому ничего не происходит.Если я изменяю OpCodes.Brtrue на OpCodes.Brfalse, я получаю сообщение «Ссылка на объект не установлена на экземпляр объекта».Такое ощущение, что я упустил что-то простое, но я не могу его найти.
//implement IINotifyPropertyChanged interface
tb.AddInterfaceImplementation(typeof(INotifyPropertyChanged));
//property changed event handler
FieldBuilder eventField = tb.DefineField("PropertyChanged", typeof(PropertyChangedEventHandler), FieldAttributes.Private);
EventBuilder eb = tb.DefineEvent("PropertyChanged", EventAttributes.None, typeof(PropertyChangedEventHandler));
MethodBuilder mbEV = tb.DefineMethod("remove_PropertyChanged", MethodAttributes.Public |
MethodAttributes.SpecialName | MethodAttributes.NewSlot |
MethodAttributes.HideBySig | MethodAttributes.Virtual |
MethodAttributes.Final, null, new[] { typeof(PropertyChangedEventHandler) });
MethodImplAttributes eventMethodFlags = MethodImplAttributes.Managed; //| MethodImplAttributes.Synchronized;
mbEV.SetImplementationFlags(eventMethodFlags);
il = mbEV.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, eventField);
il.Emit(OpCodes.Ldarg_1);
il.EmitCall(OpCodes.Call, typeof(Delegate).GetMethod("Remove", new[] { typeof(Delegate), typeof(Delegate) }), null);
il.Emit(OpCodes.Castclass, typeof(PropertyChangedEventHandler));
il.Emit(OpCodes.Stfld, eventField);
il.Emit(OpCodes.Ret);
MethodInfo miRemoveEvent = typeof(INotifyPropertyChanged).GetMethod("remove_PropertyChanged");
tb.DefineMethodOverride(mbEV, miRemoveEvent);
eb.SetRemoveOnMethod(mbEV);
mbEV = tb.DefineMethod("add_PropertyChanged", MethodAttributes.Public |
MethodAttributes.SpecialName | MethodAttributes.NewSlot |
MethodAttributes.HideBySig | MethodAttributes.Virtual |
MethodAttributes.Final, null, new[] { typeof(PropertyChangedEventHandler) });
mbEV.SetImplementationFlags(eventMethodFlags);
il = mbEV.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, eventField);
il.Emit(OpCodes.Ldarg_1);
il.EmitCall(OpCodes.Call, typeof(Delegate).GetMethod("Combine", new[] { typeof(Delegate), typeof(Delegate) }), null);
il.Emit(OpCodes.Castclass, typeof(PropertyChangedEventHandler));
il.Emit(OpCodes.Stfld, eventField);
il.Emit(OpCodes.Ret);
MethodInfo miAddEvent = typeof(INotifyPropertyChanged).GetMethod("add_PropertyChanged");
tb.DefineMethodOverride(mbEV, miAddEvent);
eb.SetAddOnMethod(mbEV);
MethodInfo msgboxMethodInfo = typeof(System.Windows.Forms.MessageBox).GetMethod("Show", BindingFlags.Public | BindingFlags.Static, null, CallingConventions.Standard, new Type[] { typeof(String) }, null);
MethodBuilder mbRaisePropertyChanged = tb.DefineMethod("RaisePropertyChanged", MethodAttributes.Virtual, null, new Type[] { typeof(string) });
il = mbRaisePropertyChanged.GetILGenerator();
System.Reflection.Emit.Label labelExit = il.DefineLabel();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, eventField);
il.Emit(OpCodes.Ldnull);
il.Emit(OpCodes.Ceq); //this is returning false
il.Emit(OpCodes.Brtrue, labelExit);
il.Emit(OpCodes.Nop); //I never get here
il.Emit(OpCodes.Ldstr, "After If");
il.EmitCall(OpCodes.Call, msgboxMethodInfo, null);
il.Emit(OpCodes.Pop);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, eventField);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Newobj, typeof(PropertyChangedEventArgs).GetConstructor(new[] { typeof(string) }));
il.EmitCall(OpCodes.Callvirt, typeof(PropertyChangedEventHandler).GetMethod("Invoke"), null);
il.Emit(OpCodes.Nop);
il.Emit(OpCodes.Nop);
il.MarkLabel(labelExit);
il.Emit(OpCodes.Ret);