Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用C#在命令模式中的命令之间共享相同的上下文?_C#_Design Patterns_Command Pattern - Fatal编程技术网

如何使用C#在命令模式中的命令之间共享相同的上下文?

如何使用C#在命令模式中的命令之间共享相同的上下文?,c#,design-patterns,command-pattern,C#,Design Patterns,Command Pattern,我已经在我的应用程序中实现了命令模式(以多支持的方式) 结构: class MultiCommand : BaseCommand abstract class BaseCommand : ICommand 工艺流程: var commandsGroup = new MultiCommand(new List<ICommand>() { new Command1(), new Comman

我已经在我的应用程序中实现了命令模式(以多支持的方式)

结构:

class MultiCommand : BaseCommand

abstract class BaseCommand : ICommand
工艺流程:

   var commandsGroup = new MultiCommand(new List<ICommand>()
            {
                new Command1(),
                new Command2(),
                new Command3(),
            });

   commandsGroup.Execute()
IServerController
的实例化将在
MultiCommand Group
初始化之前进行

如何为组中的所有命令创建这样的共享上下文

上下文类的示例:

public class CommandContext
{
    public IServerController ServerController;
    public RequiredData Data { get; set; }

    public CommandContext(){}
}
重要
最小的实现代码是

您可以在BaseCommand类(及其派生类)上有一个构造函数,该构造函数将接受某种类型的上下文类。当实例化将属于同一组的命令时,可以为它们提供所有相同的上下文对象。可能是这样的:

public class CommandContext
{
    // The object that will be the target of the commands' actions.
    public object Data { get; set; }

    // ... any other properties that might be useful as shared state between commands...
}

public abstract class BaseCommand : ICommand
{
    protected CommandContext Context { get; private set; }

    public BaseCommand(CommandContext ctx)
    {
        Context = ctx;
    }
}

public class ChangeSomethingIDCommand : BaseCommand
{
    public ChangeSomethingIDCommand(CommandContext ctx) : base(ctx)
    { }

    public void Execute()
    {
        var target = (SomeDomainClass)Context.Data;
        target.SomethingID++;
    }
}

// Elsewhere in your code (assuming 'myTargetDomainClassInstance' is
// a SomeDomainClass instance that has been instantiated elsewhere and
// represents the object upon which the commands will do work):
var ctx = new CommandContext { Data = myTargetDomainClassInstance };
var commandGroup = new MultiItemCommand(ctx, new List<ICommand>
    {
        new ChangeSomethingIDCommand(ctx),
        new Command2(ctx),
        new Command3(ctx)
    });

commandGroup.Execute();
公共类CommandContext
{
//将成为命令操作目标的对象。
公共对象数据{get;set;}
//…作为命令之间的共享状态可能有用的任何其他属性。。。
}
公共抽象类BaseCommand:ICommand
{
受保护的CommandContext上下文{get;private set;}
公共BaseCommand(CommandContext ctx)
{
上下文=ctx;
}
}
公共类ChangeSomethingIDCommand:BaseCommand
{
公共ChangeSomethingIDCommand(CommandContext ctx):基本(ctx)
{ }
public void Execute()
{
var target=(SomeDomainClass)Context.Data;
target.SomethingID++;
}
}
//代码中的其他位置(假设“myTargetDomainClassInstance”为
//已在其他位置实例化的SomeDomainClass实例,以及
//表示命令将在其上工作的对象):
var ctx=newcommandcontext{Data=myTargetDomainClassInstance};
var commandGroup=新的多项目命令(ctx,新列表
{
新的ChangeSomethingIDCommand(ctx),
新命令2(ctx),
新命令3(ctx)
});
commandGroup.Execute();

我建议做一些通用的东西。下面是一个超级简单的例子

class MultiCommand<TContext>  
{
    List<Command<TContext>> Commands;
    TContext Context;
}
类多命令
{
列出命令;
t语境;
}
1)如果要保留此接口,则必须将此上下文作为构造函数参数传递:

新的多命令(新列表()
{
新命令1(上下文),
新命令2(上下文),
新命令3(上下文),
})
2) 作为另一个选项,您可以接受委托列表而不是命令列表。 多命令将如下所示:

类多命令:ICommand
{
公共多命令(列表命令、上下文)
}
这几乎是一样的,只是多命令负责所有共享相同上下文的命令

3) 看起来多命令中的命令取决于上一个命令的结果。在这种情况下,命令模式可能不是最好的。也许您应该尝试在这里实现中间件链

接口imidware
{
无效运行(TContext上下文);
}
类链
{
私有列表处理程序;
无效登记簿(IMIDLEWARE m);
公共无效运行(TContext上下文)
{
ForEach(h=>h.Run(context));
}
}

那么如何改变你的方法呢?我最近为DDD做了一个架构,并执行了一个commad暗示原子操作(从persistence检索聚合根,应用域规则并对聚合进行排序),因此我不需要共享上下文,可以毫无顾虑地批处理多个命令

您有一个cqrs体系结构,它使用命令模式和我发布的上述策略。

My 0.02:

1) 多命令类看起来像一个

您可能希望在基本命令类中添加一个GetParentCommand()方法,并在多命令类中添加一个AddChildCommand()方法,该方法设置每个子命令的父命令

然后子命令可以从其父对象获取上下文对象。(上下文对象也应该在基类中定义。它可能是泛型类型。)

编辑:


另一个选项是将上下文对象作为Execute函数的参数:

class MultiCommand : BaseCommand 
{
     void Execute(CommandContext context) 
     {
         Children.Execute(context);
     }
}

考虑功能性风格

public class SomeMainClass{
   public void MultiCommandInit()
    {
        MultiCommand.New()
            .Add(new Command1())
            .Add(new Command2())
            .Add(new Command3())
            .SharedContext(CC => {

                CC.Data = new RequiredData();
                CC.ServerController = GetServerController();
            });

    }

    private IServerController GetServerController()
    {
        // return proper instance of server controller
        throw new NotImplementedException();
    }
}
需要此扩展方法/函数

  public static class XMultiCommand
    {
        //  How can I have a shared context like this for all Commands of the group?
        public static MultiCommand SharedContext(this MultiCommand mc, Action<CommandContext> CallBack)
        {
            var cc = new CommandContext();            
            CallBack(cc);
            mc.SharedContext = cc;
            return mc;
        }

    }
公共静态类xmulti命令
{
//如何为组中的所有命令提供这样的共享上下文?
公共静态多命令SharedContext(此多命令mc,操作回调)
{
var cc=new CommandContext();
回调(cc);
mc.SharedContext=cc;
返回mc;
}
}
最后,这些对多命令的更改

public class MultiCommand
{
    private System.Collections.Generic.List<ICommand> list;
    public List<ICommand> Commands { get { return list; } }
    public CommandContext SharedContext { get; set; }

    public MultiCommand() { }
    public MultiCommand(System.Collections.Generic.List<ICommand> list)
    {
        this.list = list;
    }
    public MultiCommand Add(ICommand cc)
    {
        list.Add(cc);
        return this;
    }

    internal void Execute()
    {
        throw new NotImplementedException();
    }
    public static MultiCommand New()
    {
        return new MultiCommand();
    }
}
公共类多命令
{
private System.Collections.Generic.List列表;
公共列表命令{get{return List;}}
公共命令上下文共享上下文{get;set;}
公共多命令(){}
公共多命令(System.Collections.Generic.List)
{
this.list=列表;
}
公共多命令添加(ICommand cc)
{
列表。添加(cc);
归还这个;
}
内部void Execute()
{
抛出新的NotImplementedException();
}
公共静态多命令New()
{
返回新的多命令();
}
}
使用功能性风格会发生很酷的事情

  • 可重用性飙升
  • 高度关注单一责任问题
  • 作文成了常态
  • 代码维护变得简单
  • Intellisense成为您的内置API(只需使用代码注释)
  • 不需要激进的OOP设计模式
  • 使用流利的代码变得非常愉快
  • 嵌套/修饰函数更易于想象和实现
  • 你永远不会重复你自己
  • 开放/封闭的原则成为你的信仰
  • 代码现在总是清晰、完整和简洁的
  • 有些人甚至说不再需要接口了
    class MultiCommand : BaseCommand 
    {
         void Execute(CommandContext context) 
         {
             Children.Execute(context);
         }
    }
    
    public class SomeMainClass{
       public void MultiCommandInit()
        {
            MultiCommand.New()
                .Add(new Command1())
                .Add(new Command2())
                .Add(new Command3())
                .SharedContext(CC => {
    
                    CC.Data = new RequiredData();
                    CC.ServerController = GetServerController();
                });
    
        }
    
        private IServerController GetServerController()
        {
            // return proper instance of server controller
            throw new NotImplementedException();
        }
    }
    
      public static class XMultiCommand
        {
            //  How can I have a shared context like this for all Commands of the group?
            public static MultiCommand SharedContext(this MultiCommand mc, Action<CommandContext> CallBack)
            {
                var cc = new CommandContext();            
                CallBack(cc);
                mc.SharedContext = cc;
                return mc;
            }
    
        }
    
    public class MultiCommand
    {
        private System.Collections.Generic.List<ICommand> list;
        public List<ICommand> Commands { get { return list; } }
        public CommandContext SharedContext { get; set; }
    
        public MultiCommand() { }
        public MultiCommand(System.Collections.Generic.List<ICommand> list)
        {
            this.list = list;
        }
        public MultiCommand Add(ICommand cc)
        {
            list.Add(cc);
            return this;
        }
    
        internal void Execute()
        {
            throw new NotImplementedException();
        }
        public static MultiCommand New()
        {
            return new MultiCommand();
        }
    }
    
    public class Command1: BaseCommand
    {
        //inject as parameter instead
        public void Execute(Context ctx)
        {
    
        }
    }