创建通用实例
我有一个实现命令模式的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<>
的子类,因此无法分配给该类型的变量。