如何使用表达式(C#)引发父类事件
我正在为Web API编写类库 我有一个基类和一个包含30个块的接口,如下所示:如何使用表达式(C#)引发父类事件,c#,.net,silverlight,event-handling,windows-phone-7,C#,.net,Silverlight,Event Handling,Windows Phone 7,我正在为Web API编写类库 我有一个基类和一个包含30个块的接口,如下所示: interface ISomethingApi { void AuthenticateAsync(string username, string password); event AsyncResponseHandler AuthenticateEnded; void GetMemberAsync(string username); event AsyncResponseHandl
interface ISomethingApi {
void AuthenticateAsync(string username, string password);
event AsyncResponseHandler AuthenticateEnded;
void GetMemberAsync(string username);
event AsyncResponseHandler<Member> GetMemberEnded;
// more...
}
但是要创建的方法太多了。我想做一些类似的事情:
public override void GetMemberAsync(string username) {
Member member;
// work done here
RaiseEvent(x => x.GetMemberEnded, new AsyncResponseArgs<Member>(member));
}
public覆盖void GetMemberAsync(字符串用户名){
成员;
//这里做的工作
RaiseEvent(x=>x.GetMemberEnded,新的AsyncResponseArgs(成员));
}
我想这是关于思考和表达
- 这样做对吗?(表演)
- 我可以阅读哪些文档来实现这一点
- 你能给我一个有效的密码吗
static class Extensions
{
public static void Raise(this EventHandler @event, object sender, EventArgs e)
{
if (@event != null)
@event(sender, e);
}
public static void Raise<T>(this EventHandler<T> @event, object sender, T e) where T : EventArgs
{
if (@event != null)
@event(sender, e);
}
}
虽然您实际上可以使用表达式,例如:
public void Raise<T>(Expression<Func<EventHandler<T>>> expr, T eventArgs)
where T : EventArgs
{
EventHandler<T> handler = expr.Compile().Invoke();
handler(this, eventArgs);
}
public void-Raise(表达式expr,T eventArgs)
其中T:EventArgs
{
EventHandler=expr.Compile().Invoke();
处理程序(此,eventArgs);
}
您可能希望去掉冗余表达式,只需使用Func
,因为您直接从类中引发事件。通过表达式,您需要编译表达式,而Func
您不需要:
public void Raise<T>(Func<EventHandler<T>> func, T eventArgs)
where T : EventArgs
{
EventHandler<T> handler = func();
handler(this, eventArgs);
}
public void-Raise(Func-Func,T eventArgs)
其中T:EventArgs
{
EventHandler=func();
处理程序(此,eventArgs);
}
您可以使用两种静态扩展方法:
static class Extensions
{
public static void Raise(this EventHandler @event, object sender, EventArgs e)
{
if (@event != null)
@event(sender, e);
}
public static void Raise<T>(this EventHandler<T> @event, object sender, T e) where T : EventArgs
{
if (@event != null)
@event(sender, e);
}
}
虽然您实际上可以使用表达式,例如:
public void Raise<T>(Expression<Func<EventHandler<T>>> expr, T eventArgs)
where T : EventArgs
{
EventHandler<T> handler = expr.Compile().Invoke();
handler(this, eventArgs);
}
public void-Raise(表达式expr,T eventArgs)
其中T:EventArgs
{
EventHandler=expr.Compile().Invoke();
处理程序(此,eventArgs);
}
您可能希望去掉冗余表达式,只需使用Func
,因为您直接从类中引发事件。通过表达式,您需要编译表达式,而Func
您不需要:
public void Raise<T>(Func<EventHandler<T>> func, T eventArgs)
where T : EventArgs
{
EventHandler<T> handler = func();
handler(this, eventArgs);
}
public void-Raise(Func-Func,T eventArgs)
其中T:EventArgs
{
EventHandler=func();
处理程序(此,eventArgs);
}
您可以使用System.ComponentModel.EventHandlerList
,这将为您带来两个好处:
1) 您将拥有FireEvent机制
2) 事件成员不使用内存,除非已订阅委托。如果您有一个包含30个事件的类,那么无论是否有订阅者,您的类的封装中都有30个指针。EventHandlerList是一个包含所有已订阅委托的单个对象。这是一张很轻的地图(不是字典)。请注意,事件键是静态对象,因此不会添加到类的封装外形中
class AsyncResponseArgs : EventArgs
{
public Member Member { get; private set; }
public AsyncResponseArgs(Member m)
{
Member = m;
}
}
interface ISomethingApi
{
void AuthenticateAsync(string username, string password);
event EventHandler<AsyncResponseArgs> AuthenticateEnded;
void GetMemberAsync(string username);
event EventHandler<AsyncResponseArgs> GetMemberEnded;
}
class BaseHttpClient : ISomethingApi
{
private EventHandlerList Events = new EventHandlerList();
public virtual void AuthenticateAsync(string username, string password)
{
throw new NotImplementedException();
}
protected static object AuthenticateEndedEvent = new object();
public event EventHandler<AsyncResponseArgs> AuthenticateEnded
{
add { Events.AddHandler(AuthenticateEndedEvent, value); }
remove { Events.RemoveHandler(AuthenticateEndedEvent, value); }
}
public virtual void GetMemberAsync(string username)
{
throw new NotImplementedException();
}
protected static object GetMemberEndedEvent = new object();
public event EventHandler<AsyncResponseArgs> GetMemberEnded
{
add { Events.AddHandler(GetMemberEndedEvent, value); }
remove { Events.RemoveHandler(GetMemberEndedEvent, value); }
}
protected void FireEvent(object key, AsyncResponseArgs e)
{
EventHandler<AsyncResponseArgs> handler = (EventHandler<AsyncResponseArgs>)Events[key];
if (handler != null)
handler(this, e);
}
}
class XmlClient : BaseHttpClient
{
public override void GetMemberAsync(string username)
{
Member member;
// process here
FireEvent(GetMemberEndedEvent, new AsyncResponseArgs(member));
}
}
类AsyncResponseArgs:EventArgs
{
公共成员成员{get;private set;}
公共异步响应搜索(成员m)
{
成员=m;
}
}
界面等距
{
void authenticateSync(字符串用户名、字符串密码);
事件处理程序。您可以使用System.ComponentModel.EventHandlerList
,这将为您带来两个好处:
1) 您将拥有FireEvent机制
2) 事件成员不使用内存,除非有订阅的委托。如果您有一个包含30个事件的类,则无论是否有订阅,您的类的封装中都有30个指针。EventHandlerList是一个包含所有订阅的委托的单个对象。它是一个非常轻量级的映射(不是字典)。请注意,事件键是静态对象,因此不会添加到类的示意图中
class AsyncResponseArgs : EventArgs
{
public Member Member { get; private set; }
public AsyncResponseArgs(Member m)
{
Member = m;
}
}
interface ISomethingApi
{
void AuthenticateAsync(string username, string password);
event EventHandler<AsyncResponseArgs> AuthenticateEnded;
void GetMemberAsync(string username);
event EventHandler<AsyncResponseArgs> GetMemberEnded;
}
class BaseHttpClient : ISomethingApi
{
private EventHandlerList Events = new EventHandlerList();
public virtual void AuthenticateAsync(string username, string password)
{
throw new NotImplementedException();
}
protected static object AuthenticateEndedEvent = new object();
public event EventHandler<AsyncResponseArgs> AuthenticateEnded
{
add { Events.AddHandler(AuthenticateEndedEvent, value); }
remove { Events.RemoveHandler(AuthenticateEndedEvent, value); }
}
public virtual void GetMemberAsync(string username)
{
throw new NotImplementedException();
}
protected static object GetMemberEndedEvent = new object();
public event EventHandler<AsyncResponseArgs> GetMemberEnded
{
add { Events.AddHandler(GetMemberEndedEvent, value); }
remove { Events.RemoveHandler(GetMemberEndedEvent, value); }
}
protected void FireEvent(object key, AsyncResponseArgs e)
{
EventHandler<AsyncResponseArgs> handler = (EventHandler<AsyncResponseArgs>)Events[key];
if (handler != null)
handler(this, e);
}
}
class XmlClient : BaseHttpClient
{
public override void GetMemberAsync(string username)
{
Member member;
// process here
FireEvent(GetMemberEndedEvent, new AsyncResponseArgs(member));
}
}
类AsyncResponseArgs:EventArgs
{
公共成员成员{get;private set;}
公共异步响应搜索(成员m)
{
成员=m;
}
}
界面等距
{
void authenticateSync(字符串用户名、字符串密码);
事件处理程序。您必须将Raisexx方法移动到父类,在父类中定义事件。确保这些方法至少受到保护
不要忘记通过局部变量调用事件,以最小化错误字段
var e=MyEvent
如果(e!=null)e(this,EventArgs.Empty);您必须将Raisexx方法移动到父类,在父类中定义事件。确保这些方法至少受到保护
不要忘记通过局部变量调用事件,以最小化错误字段
var e=MyEvent
如果(e!=null)e(this,EventArgs.Empty);您可以向基类添加一个方法,该方法将事件名称作为字符串,并通过反射引发相应的事件,如
public void Raise(String eventName, object source, EventArgs eventArgs)
{
var field = this.GetType().GetField(eventName, BindingFlags.Instance | BindingFlags.NonPublic);
if (field == null)
throw new ArgumentException("No such event: " + eventName);
var eventDelegate = (MulticastDelegate)field.GetValue(this);
if (eventDelegate != null)
foreach (var handler in eventDelegate.GetInvocationList())
handler.Method.Invoke(handler.Target, new object[] { source, eventArgs });
}
不过,我对性能一无所知。您可以向基类添加一个方法,该方法将事件名称作为字符串,并通过反射引发相应的事件,如
public void Raise(String eventName, object source, EventArgs eventArgs)
{
var field = this.GetType().GetField(eventName, BindingFlags.Instance | BindingFlags.NonPublic);
if (field == null)
throw new ArgumentException("No such event: " + eventName);
var eventDelegate = (MulticastDelegate)field.GetValue(this);
if (eventDelegate != null)
foreach (var handler in eventDelegate.GetInvocationList())
handler.Method.Invoke(handler.Target, new object[] { source, eventArgs });
}
不过,我对性能一无所知。Hi.我想只有当您有完整的事件声明(EventHandler字段+event属性)时,第一个才有效。这不是我所拥有的。然后我尝试使用表达式(可编译),但调用无法编译:类XmlClient{public void GetMemberAsync(字符串用户名){Raise(()=>base.GetMemberEnded,new AsyncResponseArgs();}}>事件'BaseHttpClient.GetMemberEnded'只能出现在+=或-=的左侧,也许使用更复杂的表达式就可以了。我刚刚尝试了Raise(expression,T eventArgs)
和Raise((x)=>x.GetMemberEnded,new AsyncResponseArgs());
。但仍然是相同的错误。我们可以看看您如何声明一个事件的示例吗?您好,如果您将声明更改为使用EventHandler
,它应该可以工作。您好。我想只有在您有完整的事件声明(EventHandler字段+事件属性)的情况下,第一个才可以工作。这不是我所拥有的。然后我尝试使用表达式(可编译),但调用无法编译:类XmlClient{public void GetMemberAsync(字符串用户名){Raise