Удаление события из DynamicObject - PullRequest
2 голосов
/ 25 января 2011

Я успешно добавил обработчики событий в мой динамический объект. Однако я не могу их удалить.

dynamic d = new MyDynamicObject();
d.MyEvent += new EventHandler(this.MyHandler);
d.MyEvent -= new EventHandler(this.MyHandler);

Когда я добавляю обработчик события, я получаю вызов TrySetMember с обработчиком в качестве аргумента, однако при удалении его значение равно нулю. Если значение равно null, откуда мне знать, какой обработчик удалить из моего внутреннего хранилища обработчиков для этого конкретного события?

Ответы [ 3 ]

1 голос
/ 25 января 2011

Трудно догадаться, в чем может быть проблема, если не посмотреть фрагмент кода.Я просто выложу что-нибудь простое, что работает:

using System;
using System.Dynamic;

class Program {
    static void Main(string[] args) {
        dynamic obj = new MyDynamicObject();
        obj.MyEvent += new EventHandler(handler);
        obj.MyEvent(null, EventArgs.Empty);
        obj.MyEvent -= new EventHandler(handler);
    }
    static void handler(object sender, EventArgs e) { }
}

class MyDynamicObject : DynamicObject {
    private EventHandler dlg = new EventHandler(delegate { });
    public override bool TryGetMember(GetMemberBinder binder, out object result) {
        result = dlg;
        return true;
    }
    public override bool TrySetMember(SetMemberBinder binder, object value) {
        dlg = (EventHandler)value;
        return true;
    }
}
0 голосов
/ 21 апреля 2011

Вы на самом деле не знаете, что вы удаляете, потому что это не работает как статические события, которые имеют add, удалите, если dlr не видит свойство статического события, он выполняет следующие эквивалентные операции динамически, когда вы делаете+= и -=.

//d.MyEvent += new EventHandler(this.MyHandler);
var temp = d.MyEvent; //temp is null
temp += new EventHandler(this.MyHandler) //temp is now MyHandler
d.MyEvent = temp; //set it back

//d.MyEvent -= new EventHandler(this.MyHandler);
var temp = d.MyEvent;  //temp is MyHandler
temp -= new EventHandler(this.MyHandler)  //temp is now null
d.MyEvent = temp; //set it back

EventHandler является MulticastDelegate, поэтому вы должны рассматривать его как коллекцию, поэтому, если в нем есть только тот обработчик событий, который вы удаляете, свойство set в концедолжен быть нулевым, так как ничего не осталось.Если бы в микс было добавлено больше событий, это было бы более понятным.

//d.MyEvent += new EventHandler(this.MyHandler);
var temp = d.MyEvent; //temp is null
temp += new EventHandler(this.MyHandler) //temp is now MyHandler
d.MyEvent = temp; //set it back

//d.MyEvent += new EventHandler(this.MyHandler2);
var temp = d.MyEvent; //temp is MyHandler
temp += new EventHandler(this.MyHandler2) //temp is now MyHandler,MyHandler2
d.MyEvent = temp; //set it back

//d.MyEvent -= new EventHandler(this.MyHandler);
var temp = d.MyEvent;  //temp is  MyHandler,MyHandler2
temp -= new EventHandler(this.MyHandler)  //temp is now MyHandler2
d.MyEvent = temp; //set it back

Если вам нужно хранить его по-другому и нужно добавить и удалить, то создайте класс хранения, чтобы обернуть ваше поведение и убедиться, что вы вернетесьэто на вашем TryGet.

public DelegateStoreage<T>{

 public void Add(T del){
    //Do your stuff
}
 public void Remove(T del){
    //Do your stuff
 }
 public static T operator +(DelegateStoreage<T> x, T y)
    {
        x.Add(y)
        return x
    }

    public static T operator -( DelegateStoreage<T> x, T y)
    {
        x.Remove(y)
        return y;
    }
}
0 голосов
/ 25 января 2011

Я думаю, вам нужно сохранить ссылку на ваш new EventHandler и удалить это:

var MyEventHandler = new EventHandler(this.MyHandler);
d.MyEvent += MyEventHandler;
d.MyEvent -= MyEventHandler;
...