2014-10-07 51 views
0

我目前正在設計新的消息翻譯系統,並且有關DI和Unity的以下問題。具有泛型的統一配置

我有以下接口:

public interface ITranslate<TInput, TOutput> 
{ 
    TOutput TranslateMessage(TInput message); 
} 

隨着具體實施如下(其中InternalMessage是我公司開發的定製類)

public class TestTranslate : ITranslate<byte[], InternalMessage> 
{ 
    InternalMessage Translate(byte[] message) 
    { 
     // Do the translation here and return the result.... 
    } 
} 

不過,我想使用統一注入翻譯實例通過構造函數加入到我的Translator服務中。用於服務中的方法。

public class TranslatorService 
{  
    private readonly ITranslator translator; 
    public TranslatorService(ITranslate translator) 
    { 
     this.translator = translator; 
    } 

    public byte[] DoTranslate(string message) 
    { 
     return translator.TranslateMessage(message); 
    } 
} 

不過我有2個問題:

1)是否有可能有ITranslate在構造不specifiying譯者將處理(我試圖保持服務 和翻譯的類型儘可能通用,所以如果需要其他翻譯,我只需要換出Translator界面的具體實現)。 2)如果這是可能的,我會怎麼做,然後我會在我的統一配置中做些什麼來做到這一點。注意:我使用的XML配置(不是我的選擇),以 配置我dependenciues等

在此先感謝

斯圖爾特

+0

您的「要在服務中的方法中使用」。顯示非通用接口的用法,這在接下來的任何地方都沒有提到......可能你只是錯過了一些聲明...... – 2014-10-08 01:03:48

+0

所以一方面,你想定義一個通用接口,但在另一方面你不需要希望它在使用/注入到TranslatorService中時是通用的? – 2014-10-08 07:35:50

+0

我有上述構造函數的原因是我不確定這是否可以完成,服務代碼僅作爲示例。 我試圖寫一個通用的翻譯類,可以實現爲調用者認爲合適,但主要的東西 我試圖避免如果可能的是讓翻譯的調用者必須指定類型,理想情況下這將是 受控由統一容器(再次,如果這是可能的話)。 – 2014-10-08 07:55:35

回答

0

經過一番思考,我認爲要做到以下幾點:

  1. 在某些時候,不同類型的消息進入並且必須被
    以某種方式翻譯成其他類型。
  2. 接收這些消息的組件/客戶端應該不知道應該如何轉換不同類型的消息。
  3. 因此,您希望實現一個通用的TranslatorService類,該類可以接收任何消息,並根據輸入消息以奇妙的方式轉換爲正確的類型。
  4. 對於每個特定的翻譯,您希望定義一個特定的通用Translator類,該Translator類自動實例化並由TranslatorService類使用,最好使用某種類型的依賴注入。

如果我的假設是正確的,我會建議以下設計。

首先,定義一個通用接口,必須由每個專用的Translator-class實現。只有使輸入型通用:

interface IMessageTranslator<TMessage> 
{ 
    object Translate(TMessage message); 
} 

然後創建TranslatorService,使得客戶可以只按任意的消息,並讓他們回結果,當且僅當該消息的翻譯存在:

class TranslatorService 
{ 
    object Translate(object message) 
    { 

    } 
} 

現在,TranslatorService必須基於消息的類型實例化正確的IMessageTranslator<T>

class TranslatorService 
{ 
    private readonly IUnityContainer _container; 

    public TranslatorService() 
    { 
     _container = new UnityContainer(); 
     _container.RegisterType(typeof(IMessageTranslator<A>), typeof(MessageTranslatorA)); 
     _container.RegisterType(typeof(IMessageTranslator<B>), typeof(MessageTranslatorB)); 
     // Etc... 
    } 

    object Translate(object message) 
    { 
     if (message == null) 
     { 
      throw new ArgumentNullException("message"); 
     } 
     var genericTranslatorDefinition = typeof(IMessageTranslator<>); 
     var translatorType = genericTranslatorDefinition.MakeGenericType(message.GetType()); 
     var translator = _container.Resolve(translatorType); 
     var translateMethod = translatorType.GetMethod("Translate", new [] { message.GetType() }); 

     return translateMethod.Invoke(translator, new object[] { message }); 
    } 
} 

注意,這是一個天真:您可以通過具有TranslatorService級封裝包含所有IMessageTranslator<T> -types您已實現,然後只需實例基於消息類型之一的容器,這樣做與團結實現一個翻譯器是否確實存在/註冊了指定的消息,並且還以它找到Translate-method的方式(最好通過InterfaceMap獲取它),但是你明白了。

如果您希望獲得更大的靈活性,您可以創建一種機制,通過掃描IMessageTranslator實現程序的程序集來自動填充容器。這樣,你只需添加一個新的實現,你就可以開始了。