给定一个接口:
IEventProvider
{
event EventHandler<string> StringAvailable;
void RequestString();
}
我想通过一些方法来检索StringAvailable
的EventInfo
,可以这样调用:EventInfo ei = GetEventInfo(providerInstance.StringAvailable)
或类似的东西。我不想传递包含其名称的字符串。
我试图滥用lambda和表达式树来提取传入的事件的名称,但无济于事。因为事件在c#中不是第一类成员,这被证明是困难的。我只是帮助找到一种在运行时获得事件名称的方法,这些代码可以由编译器静态验证,以确保该事件在编译时存在。
我现在的解决方法是从我想要使用的类中删除所有事件,并将它们更改为Action<T>
。但这并不理想。
对于那些想知道我为什么这样做的人,我想允许使用基于事件的异步模式的类在运行时使用IL生成自动适应async/await。在上面的示例界面中,适配器将包装RequestString
和StringAvailable
,并使用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();