C #/ .Net 4.0을 사용하면 dataRow가 Reflection.Emit을 통해 런타임에 정의되는 BindingList에 데이터를 저장합니다. 수신 데이터의 구조는 다양하며 외부 소스에 의해 정의됩니다. 리플렉션과 일리노이의 세계에 첫 발을 디디 며 조금 어려움을 겪은 후에 필자는 dataRow를 값으로 채우고 BindingList를 채우고 결과를 그리드에 표시 할 수있었습니다. 이제 데이터가 변경되면 INotifyPropertyChanged 인터페이스와 PropertyChangedEventHandler를 구현하려고합니다. 사용이지침으로 실행되는 코드가 있지만 RaisePropertyChanged 이벤트가 실행 중이거나 아무것도 수행하지 않는 것으로 나타나지 않습니다. 동적 버전을 ildasm.exe를 통해 일반 / 정적 버전과 비교할 때 remove_PropertyChanged 및 add_PropertyChanged 메소드의 주요 차이점을 확인할 수 있습니다. 누구나 리플렉션을 통해 INotifyPropertyChanged 인터페이스를 구현하는 몇 가지 팁이나 예제를 제공 할 수 있습니까?
추가 검토 후 PropertyChangedEventHandler가 호출되지 않도록 이벤트 필드가 null이어야합니다. RaiseProprtyChanged 메소드 빌더에 일부 메시지 상자를 추가하고if (PropertyChanged! = null)0 / false를 반환하므로 아무 일도 일어나지 않습니다. 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);
조립품의 일리노이를 수정하려고하는 경우 반사가 명확하지 않습니다. 어셈블리 잠금 문제가 발생할 수 있습니다.
해결책은이 링크를 사용하십시오.
맞춤 짜기
포스트 샤프 사용하기