【问题标题】:How to create dynamics command object如何创建动态命令对象
【发布时间】:2016-12-11 19:57:35
【问题描述】:

我创建了一些类来代表我的汽车的命令:

  • PaintCommand
  • RefuelCommand

这些类实现了ICommand接口,包含Execute(Car c)方法。

例子:

    public class RefuelCommand : ICommand
{
    public RefuelCommand()
    {
    }


    public void Execute(Car car)
    {
        car.SetFuel(100);
    }
}

我使用命令模式来初始化命令。

现在,我希望能够在不更改代码的情况下添加新的Command

假设我现在想要Change Name command

有人有想法吗?

我的想法:

创建一个描述类命令的 xml 文件。 (Name, Param) 并从中生成一个新的Command 对象。

【问题讨论】:

标签: c# oop design-patterns


【解决方案1】:

也许您需要实现一个可以接受委托作为参数的通用命令。

也就是说,可以在运行时根据需要添加任意数量的命令:

public interface ICommand
{
     void Execute(Car car);
}

public class GenericCommand : ICommand
{
     public GenericCommand(Action<Car> executePredicate)
     {
           Contract.Requires(executePredicate != null);

           ExecutePredicate = executePredicate;
     }

     private Action<Car> ExecutePredicate { get; }

     public void Execute(Car car) => ExecutePredicate(car);
}

因此,您将能够创建如下命令:

ICommand command1 = new GenericCommand
(
    car =>
    {
        // Do stuff here with a given car
    }
);

ICommand command2 = new GenericCommand
(
    car =>
    {
        // Do stuff here with a given car
    }
);

ICommand commandN = new GenericCommand
(
    car =>
    {
        // Do stuff here with a given car
    }
);

【讨论】:

  • 如何在运行时转移委托?
  • @maz 我不明白你的问题。你能详细说明一下吗?
【解决方案2】:

您可以使用 T4 模板生成代码。例如,创建这个 XML 文件并将其放在您的 bin 文件夹中:

<?xml version="1.0" encoding="utf-8" ?>  
<command>  
  <name>NameCommand</name>
  <param>Car</param>  
</command> 

现在向您的项目添加一个新项目:

  1. 在解决方案资源管理器中右键单击项目节点 > 添加 > 新建项目 > Visual C# 项目并选择文本模板。
  2. 为您的模板命名。我称它为 ICommandGenerator。

在模板中放置以下代码:

<#@ output extension=".cs" #>  
<#@ assembly name="System.Xml"#>  
<#@ import namespace="System.Xml" #> 
<#@ import namespace="System" #> 
<#@ template debug="false" hostspecific="true" language="C#" #>  
<#  
XmlDocument doc = new XmlDocument();  
// Replace this file path with yours:  
doc.Load(Host.ResolvePath(@"bin\debug\NameCommand.xml"));  
var className = doc.GetElementsByTagName("name")[0].InnerText;
var paramName = doc.GetElementsByTagName("param")[0].InnerText;
#>
namespace ConsoleApplication1
{
    public partial class <#= className #> 
    {
        public <#= className #>() {}

        public void Execute(<#= paramName #> p)
        {
            // your code here...
        }
    }
}

在解决方案资源管理器中右键单击 TT 文件,然后选择运行自定义工具。它将使用 XML 文件生成下面的类。此类将是 TT 文件的子节点,因此展开 TT 文件,您将看到此类:

namespace ConsoleApplication1
{
    public partial class NameCommand 
    {
        public NameCommand() {}

        public void Execute(Car p)
        {
            // your code here...
        }
    }
}

您可以修改 TT 文件以使用另一个命名空间而不是 ConsoleApplication。您甚至可以在 XML 文件中放入一堆 Command 类型并循环遍历所有类型并生成许多类。您可以阅读有关 T4 模板的更多信息here

这就是 EF 使用数据库优先技术生成类的方式,您可以通过使用连接字符串将其指向数据库来指示 EF。然后 EF 分析您的数据库并最终在您的项目中放置一个 .tt。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-23
    • 2018-03-12
    • 2020-10-24
    • 2011-04-29
    • 2011-03-25
    • 1970-01-01
    • 1970-01-01
    • 2014-06-03
    相关资源
    最近更新 更多