我在C#中列出了以下接口:
public interface ICommand {}
public interface ICommandDispatcher<TCommand> where TCommand : ICommand {
void Dispatch(TCommand command);
}
public interface ICommandDispatcherFactory<TDispatcher, TCommand>
where TDispatcher : ICommandDispatcher<TCommand>, new()
where TCommand : ICommand
{
TDispatcher Create();
}
到目前为止,这么好。我可以创建我支持的命令并实现他们各自的调度员和工厂:
// Commands
public class CommandFileBase : ICommand
{
private readonly string _filepath;
public CommandFileBase(string filepath) {
_filepath = filepath;
}
}
public class CommandBackupFile : CommandFileBase
{
public CommandBackupFile(string filepath) : base(filepath){}
}
public class CommandCreateFile : CommandFileBase
{
public CommandCreateFile(string filepath) : base(filepath){}
}
public class CommandDeleteFile : CommandFileBase
{
public CommandDeleteFile(string filepath) : base(filepath){}
}
// Dispatchers
public class CommandBackupFileDispatcher : ICommandDispatcher<CommandBackupFile>
{
public void Dispatch(CommandBackupFile command)
{
//work
}
}
public class CommandCreateFileDispatcher : ICommandDispatcher<CommandCreateFile>
{
public void Dispatch(CommandCreateFile command)
{
//work
}
}
public class CommandDeleteFileDispatcher : ICommandDispatcher<CommandDeleteFile>
{
public void Dispatch(CommandDeleteFile command)
{
//work
}
}
// Factories
public class CommandBackupFileDispatcherFactory
: ICommandDispatcherFactory<CommandBackupFileDispatcher, CommandBackupFile>
{
public CommandBackupFileDispatcher Create()
{
return new CommandBackupFileDispatcher();
}
}
public class CommandCreateFileDispatcherFactory
: ICommandDispatcherFactory<CommandCreateFileDispatcher, CommandCreateFile>
{
public CommandCreateFileDispatcher Create()
{
return new CommandCreateFileDispatcher();
}
}
public class CommandDeleteFileDispatcherFactory
: ICommandDispatcherFactory<CommandDeleteFileDispatcher, CommandDeleteFile>
{
public CommandDeleteFileDispatcher Create()
{
return new CommandDeleteFileDispatcher();
}
}
现在,我想创建一个&#34;容器&#34;将每个支持的命令映射到其各自的调度程序工厂并包装Dispatch调用。我想映射工厂,因为一些调度员可能会将几个命令组合在一起。例如,可能有CommandBackupAndDeleteFile命令。所以我设计了这个ICommandContainer接口:
public interface ICommandContainer<TCommand> where TCommand : ICommand {
void Dispatch(TCommand command);
}
我的问题在实现容器类时开始。我想要一个将ICommand类型映射到其调度程序工厂的字典,但我无法正确获取代码。我不确定我是否只是缺少某些东西,我的界面设计有缺陷,或者我是否完全错误。我已经尝试过类型,类型和字典类型的字典,对象和我似乎无法获得可以执行Dispatch()方法的返回对象。我也尝试使用工厂界面作为字典值,但当然是 编译器不喜欢那样。在我发现的其他容器实现中,激活器调用被转换为对象实现的接口。我不确定在我的情况下是否可行,因为我只能使用通用的Dispatcher类型。
public class CommandContainer<TDispatcher, TCommand> : IContainer
where TDispatcher : ICommandDispatcher<TCommand>, new()
where TCommand : ICommand
{
private readonly Dictionary<Type, object> _container;
public CommandContainer()
{
_container = new Dictionary<Type, object>();
_container.Add(typeof(CommandBackupFile), new CommandBackupFileDispatcherFactory());
_container.Add(typeof(CommandCreateFile), new CommandCreateFileDispatcherFactory());
_container.Add(typeof(CommandDeleteFile), new CommandDeleteFileDispatcherFactory());
}
public void Dispatch(TCommand command)
{
Type type = null;
if (_dictionary.TryGetValue(typeof(TCommand), out type))
{
var factory = Activator.CreateInstance(type); // as TDispatcher
//var dispatcher = factory.Create();
//dispatcher.dispatch(command);
}
else
{
throw new InvalidOperationException("unsupported command");
}
}
}
这是我通过将代码与此论坛上的另一个容器合并而尝试的实现。
public class TestContainer2
{
Dictionary<Type, Func<object>> registrations = new Dictionary<Type, Func<object>>();
public TestContainer2()
{
Register<CommandBackupFile, CommandBackupFileDispatcher>();
Register<CommandCreateFile, CommandCreateFileDispatcher>();
Register<CommandDeleteFile, CommandDeleteFileDispatcher>();
}
public void Register<TCommand, TDispatcher>()
where TDispatcher : ICommandDispatcher<TCommand>, new()
where TCommand : ICommand
{
registrations.Add(typeof(TCommand), () => GetInstance(typeof(TDispatcher)));
}
public object GetInstance(Type serviceType)
{
Func<object> creator;
if (registrations.TryGetValue(serviceType, out creator)) return creator();
else if (!serviceType.IsAbstract) return CreateInstance(serviceType);
else throw new InvalidOperationException("No registration for " + serviceType);
}
private object CreateInstance(Type implementationType)
{
var ctor = implementationType.GetConstructors().Single();
var parameterTypes = ctor.GetParameters().Select(p => p.ParameterType);
var dependencies = parameterTypes.Select(t => GetInstance(t)).ToArray();
return Activator.CreateInstance(implementationType, dependencies);
}
public void Dispatch<TCommand>(TCommand command)
{
var dispatcher = GetInstance(typeof(TCommand));
//dispatcher.Dispatch(command);
}
}