Anastasiia Melnyk
Anastasiia Melnyk

Reputation: 139

How to unsubscribe from event in decorator

I have base abstract class and derived class from it. When I call Method1() from derived class there is a subscription on Event. I need to create decorator for derived class and replace some functionality and I don't need that Method1() from base class was called. So I tried to cancel it subscription in construct of decorator but it doesn't work. The structure of base and derived code is legacy.

    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"
    }

Is it possible to unsubscribe from base.Method2 in decorator and subscribe with decorator.Method2?

Upvotes: 0

Views: 82

Answers (1)

Fix
Fix

Reputation: 198

So your solution is calling the OnEventInvoke of the decorator, but you are modifying the subscriptions to member. If you want to keep the composition you could do the following:

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();
    }
}

Upvotes: 1

Related Questions