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