Autor Beitrag
Palladin007
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1282
Erhaltene Danke: 182

Windows 11 x64 Pro
C# (Visual Studio Preview)
BeitragVerfasst: Sa 13.09.14 21:29 
Moin,

ich brauche den Namen eines Events, möchte dafür aber keine "Magic strings" verwenden müssen.
Bei Methoden, Feldern, Properties, etc. kann ich das Problemlos mit den LINQ-Expressions machen, Events sind aber keine Objekte, daher fällt das raus.

Hat jemand eine Idee, wie ich das anders lösen kann?

Gruß
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4798
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: So 14.09.14 09:23 
Hallo Palladin007,

meinst du das selbe wie Identify an event via a Linq Expression tree?
Palladin007 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1282
Erhaltene Danke: 182

Windows 11 x64 Pro
C# (Visual Studio Preview)
BeitragVerfasst: So 14.09.14 11:18 
Ja, so ungefähr

Am besten wäre es, wenn ich gleich das EventInfo-Objekt bekommen würde und das geht mit Teilen von dem von Emperor XLII gezeigten Code auch wunderbar.
Es hat aber den Nachteil, dass es nur die Klasse nutzen kann, die das Event deklariert und damit fällt das für mich raus.
Das "tatsächliche Event" (also die Variante mit den add- und remove-Accessors, die lässt sich damit nicht handhaben, aber damit kann ich leben.

Ich möchte hauptsächlich die EventInfo von Events bekommen, die in Interfaces deklariert sind.
Aus dem Grund kann ich den Code von Emperor XLII nicht nutzen.
Ich könnte zwar zur Laufzeit einen Typ erzeugen, der das Interfaces implementiert, wo ich dann auch eine Methode einbauen kann, die die EventInfos abfragt, aber das halte ich für etwas ungünstig und langsam ist es auch noch.
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4798
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: So 14.09.14 12:50 
Und was ist mit der EventWatcher<T>-Klasse von sacha?
Palladin007 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1282
Erhaltene Danke: 182

Windows 11 x64 Pro
C# (Visual Studio Preview)
BeitragVerfasst: So 14.09.14 14:33 
Stimmt, das funktioniert, danke :)


Edit:

Ich habe den Code mal etwas zusammen gestaucht und den Kram raus gehauen, der meiner Meinung nach nicht gebraucht wird:

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
public class EventWatcherProxy : RealProxy
{
    public static EventInfo GetEventInfo<T>(Action<T> addOrRemoveHandlerToEvent)
    {
        var eventName = GetEventName(addOrRemoveHandlerToEvent);
        return typeof(T).GetEvent(eventName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
    }
    public static string GetEventName<T>(Action<T> addOrRemoveHandlerToEvent)
    {
        var proxyType = typeof(T);

        if (!proxyType.IsInterface && !typeof(MarshalByRefObject).IsAssignableFrom(proxyType))
            throw new InvalidOperationException("The type must be an interface or implement System.MarshalByRefObject");

        var eventWatcherProxy = new EventWatcherProxy(proxyType);
        addOrRemoveHandlerToEvent((T)eventWatcherProxy.GetTransparentProxy());
        return eventWatcherProxy.EventName;
    }

    private string _eventName;

    public string EventName
    {
        get { return _eventName; }
    }

    private EventWatcherProxy(Type proxyType) : base(proxyType) { }

    public override IMessage Invoke(IMessage msg)
    {
        _eventName = SkipAddRemovePrefixes((string)msg.Properties["__MethodName"]);

        return new ReturnMessage(nullnull0null, msg as IMethodCallMessage);
    }

    private static string SkipAddRemovePrefixes(string methodName)
    {
        var addPrefix = "add_";
        var removePrefix = "remove_";

        if (methodName.Substring(0, addPrefix.Length) == addPrefix)
            methodName = methodName.Substring(addPrefix.Length);
        else if (methodName.Substring(0, removePrefix.Length) == removePrefix)
            methodName = methodName.Substring(removePrefix.Length);
        else
            throw new InvalidOperationException();

        return methodName;
    }
}


Nutzung ist jetzt denkbar einfach:

ausblenden C#-Quelltext
1:
2:
var eventName = EventWatcherProxy.GetEventName<IMyInterface>(x => x.MyEvent += null);
var eventInfo = EventWatcherProxy.GetEventInfo<IMyInterface>(x => x.MyEvent -= null);