2012-08-31 51 views
4

我有一個實現命令模式的WCF服務。使用反射,我創建了一個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<PostStatCommand> 
{ 

    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<Command>)Activator.CreateInstance(handlerType); 

// This is dumb and defeats the purpose. 
(AbstractCommandHandler<PostStatCommand>)Activator.CreateInstance(handlerType); 

幫助?

+0

是處理程序輸入的內容在理論上是 「T」 的AbstractCommandHandler? – LukeHennerley

+0

您是否嘗試過使用'CreateInstance ()'而不是'CreateInstance(Type)'? – Stijn

+1

CreateInstance 仍然需要處理程序的通用參數。 System.Activator.CreateInstance >(handlerType); – Darthg8r

回答

2

爲什麼不通過反射來調用HandleCommand

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

或者,創建一個非通用基礎類(接口也會做):

public abstract class AbstractCommandHandler 
{ 
    public abstract void HandleCommand(Command command); 
} 

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

    public abstract void HandleCommand(T command); 
} 

public class StatCommandHandler : AbstractCommandHandler<PostStatCommand> 
{ 

    public override void HandleCommand(PostStatCommand command) 
    { 

    } 
} 

,並在您RunCommand方法:

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

我使用了這個解決方案,除了用提到的第一個類代替了一個接口。 – Darthg8r

1

最好的可能性將提供一個使用Command的接口並讓你的AbstractCommandHandler<>類實現該界面。類似這樣的:

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

爲什麼?因爲通過CommandHandleCommand是唯一可以保證的。如果在設計時不知道命令類型,則無法檢查參數值。因此,編譯器不會讓你投任何東西到AbstractCommandHandler<>

換句話說,T類型的參數不會奇蹟般地變成Command,因爲您忽略了該類型的實際類型參數。它只是沒有指定。還請注意,AbstractCommandHandler<PostStatCommand>而不是AbstractCommandHandler<>的子類,因此不能分配給該類型的變量。

3

O.R Mapper關於我正在實現的接口說了些什麼,他打敗了我,你可以將通用類型轉換爲此類,然後調用方法。

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<T> : ICommandHandler 
    { 
    public void HandleCommand(Command c) 
    { 
    } 
    } 

現在應該工作

+0

+1提供了一個如何使用我提出的界面的例子:-) –