【问题标题】: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
}
);
【解决方案2】:
您可以使用 T4 模板生成代码。例如,创建这个 XML 文件并将其放在您的 bin 文件夹中:
<?xml version="1.0" encoding="utf-8" ?>
<command>
<name>NameCommand</name>
<param>Car</param>
</command>
现在向您的项目添加一个新项目:
- 在解决方案资源管理器中右键单击项目节点 > 添加 > 新建项目 > Visual C# 项目并选择文本模板。
- 为您的模板命名。我称它为 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。