2010-08-02 78 views
3

我正在一個客戶端(Silverlight)的webmethod集合接口上工作。我試圖避免爲每個webmethod編寫任何自定義代碼。所以我創建了一個ServiceCall<TResult>來處理每個調用,TResult指定了服務的返回類型(我用XmlSerializer來創建返回的實例)。客戶類公開了一個匹配每個webmethod的函數,該函數所要做的就是創建一個ServiceCall<TResult>的新實例,並將TResult指定爲方法的預期返回類型。 而且工作得很好。如何製作通用通用工廠?

我也使用Ninject(依賴注入器)來嘗試和保持一切獨立。 Ninject支持開放式仿製藥,這與我的ServiceCall<TResult>一致。

但這也意味着我正在注入對Ninject容器的引用。它隱藏了綁定到容器的依賴項ServiceCall<TResult>。所以我想改爲注入一個工廠來創建我的ServiceCall<TResult>實例。這並不棘手,但我想把它變成一個通用的通用工廠。意思我想有類似Factory<T<>>這將有一個方法public T<TU> Createinstance<TU>()

但我不知道如何創建一個類型參數本身是一個開放的genric泛型類。

它在.net中的事件可能嗎? - 或者我必須創建一個特定的ServiceCallFactory?

編輯: 我使用的接口的依賴關係,但沒有必要將它們混合到這裏的問題,所以我編輯了出了問題。

在性反應,以Timwi: 使用依賴注入(DI)的常用方法是將一個接口綁定到你的實現,只有容器知道這些綁定的。然後,您代碼反對接口。這帶來了很多好處。我可以在這裏提到更多。
無論如何,它也排除了靜態類(因爲這將是對特定類的依賴)。相反,我會指示容器(在這種情況下爲Ninject)總是以單例類行爲的方式向我發送工廠接口的相同實例。
這排除了public static class Factory<T>選項,因爲它是靜態的,如果它不是靜態的,我現在需要現在使用的每一種類型的T,都會有點挫敗擁有泛型類的目的。
建議使用「完全通用」方法來創建非泛型類(如我在ServiceCall<MyResult>而不僅僅是MyResult中所傳遞的),這或多或少是我現在正在做的事情(減去靜態類部分)。 Ninject容器有一個Get方法,就像你的第二個建議一樣。
這個問題是兩部分;首先它使我的代碼直接依賴於一個容器(Ninject),但這對我來說並不是什麼大問題。惹惱我的是,如果你從外面看我的Client,你只會看到對Ninject的依賴。你不知道,直到你運行嘗試進行調用,客戶端需要一個實現註冊與Ninject的ServiceCall工作。
但是,如果客戶構造函數採用了Factory>類型的參數,那麼它會更清晰。

在任何情況下,我會認爲這將是一個普遍的問題,所以要麼有一個共同的解決方案,或它不是一個普遍的問題,我試圖做一些愚蠢的事情) 我仍然沒有進入依賴注入,所以很可能是這種情況。

+0

是「IServiceCall」特定服務調用的例子(如「富」),或者是這個API你正在建設一個實際的接口? – 2010-08-02 17:34:37

+0

這是一個界面。我的具體實現是ServiceCall。我用它來依賴於一個接口而不是特定的實現。 但這個問題並沒有問題。我將編輯帖子。 – 2010-08-02 20:01:21

回答

4

這是你在找什麼:Generic Factory Pattern

namespace GenericFactoryPatternTestApp 
{ 
    public class Factory<T> 
    { 
     private readonly Dictionary< string, Type > _factoryDictionary = new Dictionary< string, Type >(); 

     public Factory() 
     {  
      Type[] types = Assembly.GetAssembly(typeof (T)).GetTypes(); 

      foreach (Type type in types) 
      { 
       if (!typeof (T).IsAssignableFrom(type) || type == typeof (T)) 
       { 
        // Incorrect type 
        continue; 
       } 

       // Add the type 
       _factoryDictionary.Add(type.Name, type); 
      } 
     } 

     public T Create<V>(params object[] args) 
     { 
      return (T) Activator.CreateInstance(_factoryDictionary[typeof (V).Name], args); 
     } 
    } 
} 
1

所以,如果我理解你的權利,你有一個類看起來有點像這樣:

public static class Factory<T<>> 
{ 
    public static T<TU> CreateInstance<TU>() { /* ... */ } 
} 

,然後你把它怎麼樣?喜歡這個?

var myServiceCall = Factory<ServiceCall<>>.CreateInstance<MyResult>(); 

什麼阻止你只需聲明廠這樣的...

public static class Factory<T> 
{ 
    public static T CreateInstance() { /* ... */ } 
} 

...或...這

public static class Factory 
{ 
    public static T CreateInstance<T>() { /* ... */ } 
} 

...,然後生成您的實例喜歡這個?

var myServiceCall = Factory<ServiceCall<MyResult>>.CreateInstance(); 
var myServiceCall = Factory.CreateInstance<ServiceCall<MyResult>>(); 

對不起,如果我是啞巴,但我可能會需要知道Ninject是如何工作的,以及它如何讓你在工廠通過。

+0

由於篇幅有點短暫,我會在問題中留言。 – 2010-08-02 20:22:10