none
Per Reflection.Emit erstellte Klasse INotifyPropertyChanged Interface korrekt einbinden RRS feed

  • Frage

  • Ich möchte in eine mit Reflection.Emit erstellte Klasse das INotifyPropertyChanged Interface einbinden.

    Ich binn mir nicht siche wo der fehler liegt, villeicht schafft es jemand das Problem zu lösen.

    TypeBuilder tb; //=...
    //...
    FieldBuilder eventField = tb.DefineField("m_PropertyChanged", typeof(PropertyChangedEventHandler), FieldAttributes.Public);
    
                EventBuilder eb = tb.DefineEvent("PropertyChanged", EventAttributes.None, typeof(PropertyChangedEventHandler));
    
                MethodBuilder mbEV = tb.DefineMethod("remove_PropertyChanged", MethodAttributes.Public |
                    MethodAttributes.SpecialName |
                    MethodAttributes.HideBySig | MethodAttributes.Virtual
                    , null, new[] { typeof(PropertyChangedEventHandler) });
    
                MethodImplAttributes eventMethodFlags = MethodImplAttributes.Managed;
                mbEV.SetImplementationFlags(eventMethodFlags);
                var removeIl = mbEV.GetILGenerator();
                removeIl.Emit(OpCodes.Ldarg_0);
                removeIl.Emit(OpCodes.Ldarg_0);
                removeIl.Emit(OpCodes.Ldfld, eventField);
                removeIl.Emit(OpCodes.Ldarg_1);
                removeIl.EmitCall(OpCodes.Call, typeof(Delegate).GetMethod("Remove", new[] { typeof(Delegate), typeof(Delegate) }), null);
                removeIl.Emit(OpCodes.Castclass, typeof(PropertyChangedEventHandler));
                removeIl.Emit(OpCodes.Stfld, eventField);
                removeIl.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.HideBySig | MethodAttributes.Virtual
                    , null, new[] { typeof(PropertyChangedEventHandler) });
    
                mbEV.SetImplementationFlags(eventMethodFlags);
                var addIl = mbEV.GetILGenerator();
                addIl.Emit(OpCodes.Ldarg_0);
                addIl.Emit(OpCodes.Ldarg_0);
                addIl.Emit(OpCodes.Ldfld, eventField);
                addIl.Emit(OpCodes.Ldarg_1);
                addIl.EmitCall(OpCodes.Call, typeof(Delegate).GetMethod("Combine", new[] { typeof(Delegate), typeof(Delegate) }), null);
                addIl.Emit(OpCodes.Castclass, typeof(PropertyChangedEventHandler));
                addIl.Emit(OpCodes.Stfld, eventField);
                addIl.Emit(OpCodes.Ret);
                MethodInfo miAddEvent = typeof(INotifyPropertyChanged).GetMethod("add_PropertyChanged");
                tb.DefineMethodOverride(mbEV, miAddEvent);
                eb.SetAddOnMethod(mbEV);
    
    //-*-*-*-*-*-*-*-*-
    
    
    MethodBuilder mbRaisePropertyChanged = tb.DefineMethod("RaisePropertyChanged", MethodAttributes.Virtual, null, new Type[] { typeof(string) });
    
                var RaiseIl = mbRaisePropertyChanged.GetILGenerator();
                System.Reflection.Emit.Label RaiseIlExitLabel = RaiseIl.DefineLabel();
                RaiseIl.Emit(OpCodes.Ldarg_0);
                RaiseIl.Emit(OpCodes.Ldfld, eventField);//if
                RaiseIl.Emit(OpCodes.Ldnull);
                RaiseIl.Emit(OpCodes.Ceq);
                RaiseIl.Emit(OpCodes.Brtrue, RaiseIlExitLabel);//endif
                RaiseIl.Emit(OpCodes.Pop);
                RaiseIl.Emit(OpCodes.Ldarg_0);
                RaiseIl.Emit(OpCodes.Ldfld, eventField);
                RaiseIl.Emit(OpCodes.Ldarg_0);
                RaiseIl.Emit(OpCodes.Ldarg_1);
                RaiseIl.Emit(OpCodes.Newobj, typeof(PropertyChangedEventArgs).GetConstructor(new[] { typeof(string) }));
                RaiseIl.EmitCall(OpCodes.Callvirt, typeof(PropertyChangedEventHandler).GetMethod("Invoke"), null);
                RaiseIl.Emit(OpCodes.Nop);
                RaiseIl.Emit(OpCodes.Nop);
                RaiseIl.MarkLabel(RaiseIlExitLabel);
                RaiseIl.Emit(OpCodes.Ret);
    
    //*-*-*-*-*-*-*-*-*--
    
    //Der RaisePropertyChangedaufruf im setter
    
     MethodBuilder setPropMthdBldr =
                    _tb.DefineMethod("set_" + _propertyName,
                      MethodAttributes.Public |
                      MethodAttributes.SpecialName |
                      MethodAttributes.HideBySig,
                      null, new[] { _propertyType });
    
                ILGenerator setIl = setPropMthdBldr.GetILGenerator();
                System.Reflection.Emit.Label exitSet = setIl.DefineLabel();
    
                setIl.Emit(OpCodes.Ldarg_0);
                setIl.Emit(OpCodes.Ldarg_1);
                setIl.Emit(OpCodes.Stfld, fieldBuilder);
    
                /*INotifyPropertyChanged aufruf*/
                setIl.Emit(OpCodes.Newobj, typeof(PropertyChangedEventArgs).GetConstructor(new[] { typeof(string) })); 
                setIl.Emit(OpCodes.Ldstr, _propertyName);
                setIl.EmitCall(OpCodes.Callvirt, typeof(PropertyChangedEventHandler).GetMethod("Invoke"), null);
    
    
                setIl.Emit(OpCodes.Nop);
                setIl.MarkLabel(exitSet);
                setIl.Emit(OpCodes.Ret);


    • Bearbeitet Robin4444 Montag, 31. März 2014 10:26
    Montag, 31. März 2014 10:14