C# 通用接口的运行时强制转换

C# 通用接口的运行时强制转换,c#,generics,casting,inversion-of-control,service-locator,C#,Generics,Casting,Inversion Of Control,Service Locator,我有一个命令处理例程,需要从我的IOC容器中获取一个处理器对象并在其上调用ProcessCommand,处理器是实现通用接口的具体对象: public interface ICommandProcessor<in T> where T : Command { Error ProcessCommand(T command); } 公共接口ICommandProcessor,其中T:Command { 错误处理命令(T命令); } 我遇到的问题

我有一个命令处理例程,需要从我的IOC容器中获取一个处理器对象并在其上调用ProcessCommand,处理器是实现通用接口的具体对象:

public interface ICommandProcessor<in T> where T : Command
{        
    Error ProcessCommand(T command);
}
公共接口ICommandProcessor,其中T:Command
{        
错误处理命令(T命令);
}
我遇到的问题是,当我试图检索处理器时,我只有一个通过基类(command)对command对象的引用,所以我不知道T的类型(运行时除外)

我引入了第二个非通用接口

public interface ICommandProcessorGeneric
{

}

public interface ICommandProcessor<in T>:ICommandProcessorGeneric where T : Command
{        
    Error ProcessCommand(T command);
}
公共接口ICommandProcessorGeneric
{
}
公共接口ICommandProcessor:ICommandProcessorGeneric其中T:Command
{        
错误处理命令(T命令);
}
并可以从IOC容器中检索处理器,如下所示:

 protected virtual CommandProcessingResult RecognizeAndProcessCommand<T>(T command) where T : Command
 {
    ICommandProcessor<T> commandProcessor;

    try
    {
        Debug.WriteLine(String.Format( "---- Looking for processor for type {0}", command.GetType().Name));
        var g = ServiceLocator.GetInstance<ICommandProcessorGeneric>(command.GetType().Name);                
        commandProcessor = g as ICommandProcessor<T>;  //returns null!!
        Debug.WriteLine(String.Format("---- Got Processor {0}", g.GetType().Name));
    }
    catch (Exception ex)
    {
        //handle the exception
    }
    return commandProcessor.ProcessCommand(command);
}
受保护的虚拟命令processingresult RecognizeAndProcessCommand(T command),其中T:command
{
ICommandProcessor命令处理器;
尝试
{
WriteLine(String.Format(----查找类型{0}的处理器,command.GetType().Name));
var g=ServiceLocator.GetInstance(command.GetType().Name);
commandProcessor=g作为ICommandProcessor;//返回null!!
WriteLine(String.Format(--Got Processor{0}),g.GetType().Name));
}
捕获(例外情况除外)
{
//处理异常
}
返回commandProcessor.ProcessCommand(命令);
}
问题是commandProcessor随后为null,因为T是Command,而在运行时我知道T是派生类型。从IOC容器返回的对象g是正确的processorm,但是我看不出如何将g强制转换为允许我访问ProcessCommand方法的类型

我还应该指出,对该方法的调用无法在编译时确定命令的类型,因为该命令仅通过引用at ID字段从数据库中检索并反序列化。

因此,我在过去所做的基本工作是为您的命令处理器创建一个抽象基类和一个通用基类:

public abstract class CommandProcessor
{
    public abstract Error ProcessCommand(Command command);
}

public abstract class CommandProcessor<TCommand> where TCommand : Command
{
    public override Error ProcessCommand(Command command)
    {
        if (command is TCommand == false)
            throw new ArgumentException("command should be of type TCommand");

        var cast = (TCommand)command;

        return this.ProcessCommand(cast);
    }

    public abstract Error ProcessCommand(TCommand command);
}
公共抽象类CommandProcessor
{
公共抽象错误处理命令(Command命令);
}
公共抽象类CommandProcessor,其中TCommand:Command
{
公共覆盖错误处理命令(命令命令)
{
if(命令为TCommand==false)
抛出新ArgumentException(“命令应为TCommand类型”);
var cast=(TCommand)命令;
返回这个.ProcessCommand(cast);
}
公共抽象错误处理命令(TCommand命令);
}
现在,您不需要根据所使用的命令类型执行任何特殊操作:

protected virtual CommandProcessingResult RecogniseAndProccessCommand<T>
    (T command) where T : Command
{
    var commandProcessor = (CommandProcessor)ServiceLocator.GetInstance<ICommandProcessorGeneric>(typeof(T).Name);

    return commandProcessor.ProcessCommand(command);
}
受保护的虚拟命令processingresult recognizeandprocessCommand
(T命令),其中T:command
{
var commandProcessor=(commandProcessor)ServiceLocator.GetInstance(typeof(T).Name);
返回commandProcessor.ProcessCommand(命令);
}

如果您在泛型方法内部进行强制转换,则说明您使用了错误的方法。理想情况下,如果在本例中避免使用
ServiceLocator
模式,而是将
ICommandProcessor
注入包含
RecognizeAndProcessCommand
的实例(或方法,如果确实必须)中,则应使用
ICommandProcessor
约束
方法,这能解决问题吗?我现在觉得“命令”这个词很奇怪。。。键入的次数太多。我正试图避免将命令强制转换为TCommand。关键是您的
ServiceLocator
将获得正确版本的
CommandProcessor
,它将具有
ProcessCommand
的正确实现,但是您仍然可以在编译时调用基
ProcessCommand
,而不必担心当时的类型。抱歉,这正是我最后所做的,在抽象基类中进行的转换很好。