Как отписаться от события в декораторе - PullRequest
0 голосов
/ 01 февраля 2019

У меня есть базовый абстрактный класс и производный класс от него.Когда я вызываю Method1 () из производного класса, на Event появляется подписка.Мне нужно создать декоратор для производного класса и заменить некоторые функциональные возможности, и мне не нужно, чтобы вызывался Method1 () из базового класса.Поэтому я попытался отменить подписку в конструкторе декоратора, но это не работает.Структура базового и производного кода является устаревшей.

    abstract class Base {
        public event Action Event;
        public abstract void Method1();
        public virtual void Method2(){ Console.WriteLine("Base Method2 call"); }
        public void OnEventInvoke() { Event?.Invoke();}
    }

    class Derived : Base{
        public override void Method1() { Event += Method2;}
    }

    class Decorator: Base {
        private Base b;
        public Decorator(Base b){
            this.b = b;
            b.Event -= base.Method2;
            b.Event += Method2;
        }
        public override void Method1(){}
        public override void Method2(){Console.WriteLine("Decorator Method2 call");}
    }

    static void Main(string[] args){
        var derived = new Derived();
        derived.Method1();
        derived.OnEventInvoke();
        var decorator = new Decorator(derived);
        decorator.OnEventInvoke();  //need "Decorator Method2 call"
    }

Можно ли отписаться от base.Method2 в decorator и подписаться на decorator.Method2?

1 Ответ

0 голосов
/ 01 февраля 2019

Итак, ваше решение вызывает OnEventInvoke декоратора, но вы изменяете подписку на член.Если вы хотите сохранить композицию, вы можете сделать следующее:

class Decorator : Base
{
    private Base b;
    public Decorator(Base b)
    {
        this.b = b;
        b.Event -= b.Method2;
        b.Event += Method2;
    }
    public override void Method1() { }
    public override void Method2() { Console.WriteLine("Decorator Method2 call"); }

    public override void OnEventInvoke()
    {
        b.OnEventInvoke();
    }
}
...