本文介绍了装饰有几个界面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在努力装饰+接口.假设我有以下行为"界面:

I am always struggling with decoration + interfaces. Say I have the following 'behavior' interfaces :

interface IFlyable { void Fly();}
interface ISwimmable { void Swim();}

主界面

interface IMainComponent { void DoSomethingA(); void DoSomethingB();}

主界面上的装饰器

    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 :

  1. 情况并非如此(运行时的Cast异常),看起来装饰器"实现了一个接口
  2. 这是不可扩展的,我需要添加每个新接口(不要忘记此添加)

另一种解决方案是添加手动投射"以传播装饰树:

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

但是问题是:

  1. 在调用GetAs()之后,调用者可以操纵包装的对象.
  2. 如果在调用GetAs之后使用IMainComponent中的方法,这可能导致混乱/不必要的行为(类似((IMainComponent)GetAs()).DoSomethingB(); ==>这可能会调用包装对象的实现),而不是完整的装饰.
  3. 需要调用GetAs()方法,并且退出带有强制转换/常规"As"的代码将无效.

您如何解决/解决此问题?是否有解决此问题的模式?

How to you approch/resolve this issue ? Is there a pattern addressing this issue ?

PD:我的问题是最终的C#实现,但是解决方案可能更广泛.

PD : my question is for a final C# implementation but maybe the solution is more broad.

推荐答案

您将需要为每个接口创建单独的装饰器.一种替代方法是为您的服务和通用装饰器使用通用接口.例如:

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

这篇关于装饰有几个界面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-13 18:52