如何在不对其名称进行硬编码的情况下以编程方式检索事件的EventInfo?

时间:2016-10-27 18:46:14

标签: c# .net reflection

给定一个界面:

IEventProvider
{
    event EventHandler<string> StringAvailable;

    void RequestString();
}

我想通过某种方法为EventInfo检索StringAvailable,可以这样调用:EventInfo ei = GetEventInfo(providerInstance.StringAvailable)或其他类似的方法。我不想传递包含其名称的字符串。

我试图滥用lambdas和表达式树来提取传入的事件的名称但无济于事。因为事件不是C#中的头等成员,所以事实证明这很困难。我只是帮助找到一种在运行时获取事件名称的方法,其代码可以由编译器进行静态验证,以确保在编译时存在事件。

我现在的解决方法是从我想要使用的类中删除所有事件,并将它们更改为Action<T>。但这并不理想。

对于那些想知道为什么我这样做的人,我想允许使用基于事件的异步模式的类在运行时使用IL生成自动适应async / await。在上面的示例界面中,适配器将包裹RequestStringStringAvailable并使用public async Task<string> RequestStringAsync()公开DynamicMethod

2 个答案:

答案 0 :(得分:1)

如果我理解正确,我会写一个像这样的扩展方法

 public static class Ext
{
    public static Task<string> RequestStringAsync(this IEventProvider cls)
    {
        var tcs = new TaskCompletionSource<string>();
        EventHandler<string> handler = null;

        handler = (o, s) =>
        {
            tcs.SetResult(s);
            cls.StringAvailable -= handler;
        };

        cls.StringAvailable += handler;

        cls.RequestString();

        return tcs.Task;
    }
}

并使用它

public class MyEventProvider : IEventProvider
{
    public event EventHandler<string> StringAvailable;

    public void RequestString()
    {
        var temp = StringAvailable;
        if (temp != null) temp(this, "aaaaa");
    }
}
var p = new MyEventProvider();
var str = await p.RequestStringAsync();

答案 1 :(得分:1)

您可以将ProviderInfo实例传递给每次反射获取EventInfo的方法。

以下是三个例子:

var singleEvent = GetEventInfo(providerInstance);

public static EventInfo GetEventInfo(IEventProvider eventProvider)
{
    var type = eventProvider.GetType();
    return type.GetEvent(nameof(eventProvider.StringAvailable));
}

这个使用硬编码的nameof-operator获取事件。

var singleEventWithName = GetEventInfo(providerInstance, nameof(providerInstance.StringAvailable));

public static EventInfo GetEventInfo(IEventProvider eventProvider, string name)
{
    var type = eventProvider.GetType();
    return type.GetEvent(name);
}

您可以在此处使用nameof-operator传递名称。

var allEvents = GetEventInfos(providerInstance);

public static EventInfo[] GetEventInfos(IEventProvider eventProvider)
{
    return eventProvider.GetType().GetEvents();
}

这个只返回提供者的所有EventInfos。

我希望这会有所帮助。

修改

更好的是:

var eventInfo = GetEventInfo(nameof(providerInstance.StringAvailable));

public static EventInfo GetEventInfo(string name)
{
    return typeof(IEventProvider).GetEvent(name);
}