I am always struggling with decoration + interfaces. Say I have the following 'behavior' interfaces :
interface IFlyable { void Fly();}
interface ISwimmable { void Swim();}
A main interface
interface IMainComponent { void DoSomethingA(); void DoSomethingB();}
A decorator on the main interace
public class Decorator : IMainComponent
{
private readonly IMainComponent decorated;
[..]
public virtual void DoSomethingA()
{
decorated.DoSomethingA();
}
public virtual void DoSomethingB()
{
decorated.DoSomethingB();
}
}
My issue is how to forward all the interfaces implemented by the decorated object to the decorator. A solution is to make the decorator implementation the interfaces :
public class Decorator : IMainComponent, IFlyable, ISwimmable
{
[..]
public virtual void Fly()
{
((IFlyable)decorated).Fly();
}
public virtual void Swim()
{
((ISwimmable)decorated).Swim();
}
But I don't like it because :
An other solution is to add "a manual cast" that propagates throw the decoration tree :
public class Decorator : IMainComponent
{
public T GetAs<T>()
where T : class
{
//1. Am I a T ?
if (this is T)
{
return (T)this;
}
//2. Maybe am I a Decorator and thus I can try to resolve to be a T
if (decorated is Decorator)
{
return ((Decorator)decorated).GetAs<T>();
}
//3. Last chance
return this.decorated as T;
}
But the issues are :
How to you approch/resolve this issue ? Is there a pattern addressing this issue ?
PD : my question is for a final C# implementation but maybe the solution is more broad.
In object-oriented programming, the decorator pattern is a design pattern that allows behavior to be added to an individual object, dynamically, without affecting the behavior of other objects from the same class.
Decorator Method is a Structural Design Pattern which allows you to dynamically attach new behaviors to objects without changing their implementation by placing these objects inside the wrapper objects that contains the behaviors.
The Decorator pattern is best when the decorators modify the behavior of the methods in the interface. A decorator can add methods, but added methods don't carry through when you wrap in another decorator.
Decorators are functions (or classes) that provide enhanced functionality to the original function (or class) without the programmer having to modify their structure.
You will need to create separate decorators for each interface. An alternative is to use a generic interface for your services and a generic decorator. For example:
public interface ICommandService<TCommand>
{
Task Execute(TCommand command);
}
public class LoggingCommandService<TCommand> : ICommandService<TCommand>
{
public LoggingCommandService(ICommandService<TCommand> command, ILogger logger)
{
...
}
public async Task Execute(TCommand command)
{
// log
await this.command.Execute(command);
// log
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With