创建通用实例

我有一个实现命令模式的WCF服务。 使用reflection,我创建了一个Dictionary,其中键是命令类型,值是CommandHandler。 我们的想法是从WCF接收命令,使用字典获取处理程序类型,然后使用激活器创建处理程序的实例。

public CommandResponse RunCommand(Command command) { _logger.Trace("Running Command"); var handlerType = HandlerMap[command.GetType()]; var handler = (AbstractCommandHandler)Activator.CreateInstance(handlerType); handler.HandleCommand(command); return new PostStatCommandResponse(); } public class StatCommandHandler : AbstractCommandHandler { public override void HandleCommand(PostStatCommand command) { } } 

问题是Activator.CreateInstance返回一个对象,而不是一个强类型的commandhandler。 我需要能够调用HandleCommand,但无法弄清楚如何将它转换为基础AbstractCommandHandler

 // Syntax error. Gotta provide type to generic (AbstractCommandHandler)Activator.CreateInstance(handlerType); // Casting error at run time (AbstractCommandHandler)Activator.CreateInstance(handlerType); // This is dumb and defeats the purpose. (AbstractCommandHandler)Activator.CreateInstance(handlerType); 

救命?

为什么不通过reflection调用HandleCommand

 var handler = Activator.CreateInstance(handlerType); handlerType.GetMethod("HandleCommand").Invoke(handler, new [] {command}); 

或者,创建一个非generics基类(接口也可以):

 public abstract class AbstractCommandHandler { public abstract void HandleCommand(Command command); } public abstract class AbstractCommandHandler : AbstractCommandHandler { public override void HandleCommand(Command command) { HandleCommand((T) command); } public abstract void HandleCommand(T command); } public class StatCommandHandler : AbstractCommandHandler { public override void HandleCommand(PostStatCommand command) { } } 

并在您的RunCommand方法中:

 var handler = Activator.CreateInstance(handlerType); ((AbstractCommandHandler)handler).HandleCommand(command); 

什么OR Mapper对我正在实现的接口说了什么,他打败了我,你可以将generics类型转换为此,然后调用该方法。

  Command c = new PostStatCommand(); var genericType = typeof(AbstractCommandHandler<>).MakeGenericType(c.GetType()); ICommandHandler handler = (ICommandHandler)Activator.CreateInstance(genericType); handler.HandleCommand(c); 

使AbstractCommandHandler实现ICommandHandler

  public class AbstractCommandHandler : ICommandHandler { public void HandleCommand(Command c) { } } 

应该现在工作

最好的可能性是提供一个使用Command的接口,并让您的AbstractCommandHandler<>类实现该接口。 像这样的东西:

 public interface ICommandHandler { void HandleCommand(Command command); } 

为什么? 因为将Command传递给HandleCommand是唯一可以保证的事情。 如果在设计时未知命令类型,则无法检查参数值。 因此,编译器不会让你向AbstractCommandHandler<>任何东西。

换句话说,类型T的参数不会神奇地变成Command ,因为你省略了类型的实际类型参数。 它将是未指定的。 另请注意, AbstractCommandHandler 不是 AbstractCommandHandler<>的子类,因此无法分配给该类型的变量。