Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

[erledigt] Per Reflection.Emit einen Event mit explizitem add und remove generieren
Robin0
myCSharp.de - Member



Dabei seit:
Beiträge: 213

Themenstarter:

[erledigt] Per Reflection.Emit einen Event mit explizitem add und remove generieren

beantworten | zitieren | melden

Hallo,

Ich versuche gerade INotifyPropertyChanged in eine per Reflection.Emit erstelle klasse einzubinden.

Ich hänge gerade fest, weil ich es nicht hinbekommen einen add und einen remove handler zu erstellen.


private PropertyChangedEventHandler PropertyChange;

/*Eig nur der untere teil*/
public event PropertyChangedEventHandler PropertyChanged
        {
            add { PropertyChange += value; }
            remove { PropertyChange -= value; }
        }

Weiß vielleicht jemand weiter, oder kennt ein buch über Reflection.emit?
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Robin0 am .
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo Robin0,

willst du diese Konstruktion genau so, oder ist das nur ein Beispiel, das du im konkreten Fall noch abwandeln willst. Denn so wie die Konstruktion dasteht, macht sie aus meiner Sicht keinen Sinn und könnte ohne weiteres komplett durch folgende Zeile ersetzt werden:

public event PropertyChangedEventHandler PropertyChanged;

herbivore
private Nachricht | Beiträge des Benutzers
Robin0
myCSharp.de - Member



Dabei seit:
Beiträge: 213

Themenstarter:

beantworten | zitieren | melden

Ich bekomm ne fehlermeldung dass:
Fehler
{"Die Methode \"add_PropertyChanged\" im Typ \"Dynamic.DynamicType\" der Assembly \"Dynamic.DynamicAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null\" hat keine Implementierung.":"Dynamic.DynamicType"}

Der fehler tritt bei "_tb.CreateType();" auf

Mein reflection code dazu ist:


/*_tb is mein TypeBuilder*/

_tb.DefineEvent("PropertyChanged", EventAttributes.None, typeof(PropertyChangedEventHandler));

/*Jedes Feld bekommt bei mir ein eigenschaft, den setter baue ich so auf*/
MethodBuilder setPropMthdBldr =
                _tb.DefineMethod("set_" + _propertyName,
                  MethodAttributes.Public |
                  MethodAttributes.SpecialName |
                  MethodAttributes.HideBySig,
                  null, new[] { _propertyType });

            ILGenerator setIl = setPropMthdBldr.GetILGenerator();
            System.Reflection.Emit.Label modifyProperty = setIl.DefineLabel();
            System.Reflection.Emit.Label exitSet = setIl.DefineLabel();

            setIl.MarkLabel(modifyProperty);
            setIl.Emit(OpCodes.Ldarg_0);
            setIl.Emit(OpCodes.Ldarg_1);
            setIl.Emit(OpCodes.Stfld, fieldBuilder);

            /*INotifyPropertyChanged aufruf*/
            setIl.Emit(OpCodes.Ldarg_0);
            setIl.Emit(OpCodes.Ldstr, _propertyName);
            setIl.EmitCalli(OpCodes.Calli, System.Runtime.InteropServices.CallingConvention.ThisCall, typeof(void), new[] { typeof(Object), typeof(PropertyChangedEventArgs) });
             /**/

            setIl.Emit(OpCodes.Nop);
            setIl.MarkLabel(exitSet);
            setIl.Emit(OpCodes.Ret);
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Robin0 am .
private Nachricht | Beiträge des Benutzers
DerKleineTomy
myCSharp.de - Member



Dabei seit:
Beiträge: 106

beantworten | zitieren | melden

In deinem Code fügst du auch keine Add oder Remove Methode zu dem Event hinzu.

EventBuilder ev = _tb.DefineEvent("PropertyChanged", EventAttributes.None, typeof(PropertyChangedEventHandler)); 

MethodBuilder addMethod = ...;
// Define Method ...
//...
ev.SetAddOnMethod(addMethod);

Daher ist auch keine Implementierung vorhanden.
private Nachricht | Beiträge des Benutzers
Robin0
myCSharp.de - Member



Dabei seit:
Beiträge: 213

Themenstarter:

beantworten | zitieren | melden

Habs denke ich:


            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);

Das einzige was ich jetz noch machen muss is meine "RaisePropertyChanged" im setter der variable aufzurufen

RaisePropertyChanged:


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);

Ich hab das erstellen der eigenschaften in eine Methode ausgelagert, und kenne "mbRaisePropertyChanged" da nicht, wie rufe ich die dann auf?? der typ is ja nochnich erstellt und ich kann die Methode dann nichg mit Type.GetMethod() suchen, da der Typ nochnich existiert.
private Nachricht | Beiträge des Benutzers
Robin0
myCSharp.de - Member



Dabei seit:
Beiträge: 213

Themenstarter:

beantworten | zitieren | melden

Soo nach langem sochen habe ich eine Losung gefunden:

Hier ist alles ziemlich genau beschrieben :).
Dynamically generating types to implement INotifyPropertyChanged

Die *WrpapMethod* Funktioniert zwar nicht, aber das ist nebensache man kann den aufruf ja direkt in den setter einbauen.
private Nachricht | Beiträge des Benutzers