Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用表达式(C#)引发父类事件_C#_.net_Silverlight_Event Handling_Windows Phone 7 - Fatal编程技术网

如何使用表达式(C#)引发父类事件

如何使用表达式(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

我正在为Web API编写类库

我有一个基类和一个包含30个块的接口,如下所示:

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