C# 删除匿名事件处理程序

C# 删除匿名事件处理程序,c#,wcf,C#,Wcf,我有以下代码,其中SprintServiceClient是对WCF服务的引用- public class OnlineService { private SprintServiceClient _client; public OnlineService() { _client = new SprintServiceClient(); } public void AddMemberToTeam(MemberModel user, int p

我有以下代码,其中SprintServiceClient是对WCF服务的引用-

public class OnlineService
{
    private SprintServiceClient _client;
    public OnlineService()
    {
        _client = new SprintServiceClient();
    }

    public void AddMemberToTeam(MemberModel user, int projectId, Action<int> callback)
    {
        _client.AddMemberToTeamCompleted += (s, e) => callback(e.Result);
        _client.AddMemberToTeamAsync(user.ToUser(), projectId);
    }
}
公共类在线服务
{
私有SprintServiceClient _客户端;
公共在线服务()
{
_client=新的SprintServiceClient();
}
public void AddMemberToTeam(MemberModel用户、int projectId、操作回调)
{
_client.AddMemberToTeamCompleted+=(s,e)=>回调(e.Result);
_client.AddMemberToTeamAsync(user.ToUser(),projectId);
}
}
问题是,每次调用AddMemberToTeam时,都会向client.AddMemberToTeamCompleted添加另一个回调

i、 e第一次调用AddMemberToTeam时,回调调用一次,第二次调用AddMemberToTeam时,回调调用两次

一旦调用了eventhandler,有没有办法从AddMemberToTeamCompleted中删除eventhandler,或者使用另一个接受回调的方法?

没有办法

显然,蒂姆和马克还有一个很好的解决办法

但是您总是可以命名它们,并在此方法上对命名的eventhandler执行
-=

猜测您的事件:

_client.AddMemberToTeamCompleted += OnAddMemberToTeamCompleted;


下一个问题是在侦听器中获取此回调。也许将其放在EventArgs中的属性上(但我同意,这感觉有点脏)

您可以从内部引用您的匿名方法,只要您首先将委托分配给变量:

EventHandler<SomeEventArgs> handler = null;
handler = (s, e) =>
    {
        _client.AddMemberToTeamCompleted -= handler;
        callback(e.Result);
    };

_client.AddMemberToTeamCompleted += handler;
EventHandler=null;
处理程序=(s,e)=>
{
_client.AddMemberToTeamCompleted-=处理程序;
回调(即结果);
};
_client.AddMemberToTeamCompleted+=处理程序;

请注意,您需要声明变量并单独分配它,否则当您在方法体中使用它时,编译器会认为它未初始化。

创建自取消订阅事件处理程序的诀窍是捕获处理程序本身,以便您可以在
-=
中使用它。不过,还有一个声明和明确分配的问题;所以我们不能像这样做:

EventHandler handler = (s, e) => {
    callback(e.Result);
    _client.AddMemberToTeamCompleted -= handler; // <===== not yet defined     
};

要删除它,您需要一个引用。假设“AddMemberToTeamCompleted”是用“event”关键字定义的(只保留-=和+=运算符),则必须在委托实例中维护一个变量。第一次创建并添加它,下次不要添加任何内容,关闭时删除。可能重复的“我”似乎在这里缺少某些内容。。。有人能解释一下为什么在创建匿名方法的委托时捕获处理程序的值时处理程序不为null吗?赋值运算符的右侧不是先处理的吗?那么,在将处理程序分配给新的匿名委托之前,不应该捕获处理程序的值吗?然而,这段代码似乎有效,所以我很好奇为什么它有效,而不是试图删除空处理程序。匿名方法中外部变量的值捕获是在handler赋值之后发生的吗?@reirab在c#中,捕获的是变量,而不是当前值。啊,好的,谢谢。我知道C#编译器实际上创建了一个包含匿名方法和被捕获变量的新对象,但是,我以前没有意识到新对象中的变量实际上是外部类使用的变量,而不仅仅是它的副本。有趣。
EventHandler handler = (s, e) => {
    callback(e.Result);
    _client.AddMemberToTeamCompleted -= handler; // <===== not yet defined     
};
EventHandler handler = null;
handler = (s, e) => {
    callback(e.Result);
    _client.AddMemberToTeamCompleted -= handler;        
};
_client.AddMemberToTeamCompleted += handler;