如何通过编程方式检索事件的EventInfo而不需要对其名称进行硬编码



给定一个接口:

IEventProvider
{
    event EventHandler<string> StringAvailable;
    void RequestString();
}

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

我试图滥用lambda和表达式树来提取传入的事件的名称,但无济于事。因为事件在c#中不是第一类成员,这被证明是困难的。我只是帮助找到一种在运行时获得事件名称的方法,这些代码可以由编译器静态验证,以确保该事件在编译时存在。

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

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

你可以将ProviderInfo实例传递给一个方法,该方法根据每个反射获取EventInfo。

下面是三个例子:

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

使用硬编码的操作符名称获取事件。

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

这里你可以用name - of操作符传递名称。

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

这个返回提供商的所有eventinfo。

我希望这对你有帮助。

编辑

最好是:

var eventInfo = GetEventInfo(nameof(providerInstance.StringAvailable));
public static EventInfo GetEventInfo(string name)
{
    return typeof(IEventProvider).GetEvent(name);
}

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

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

相关内容

  • 没有找到相关文章

最新更新