6

我有一個服務,它的構造函數需要IMyDependency。 IMyDependency,MyDependency和服務都在同一個程序集中。 MyDependency有一個公共的無參數構造函數。funq - 通過約定自動裝配

令我驚訝的是,這並不工作:

container.RegisterAutoWired<IMyDependency>(); 

它拋出一個 「System.NullReferenceException」。

如果我這樣做它的工作原理:

container.RegisterAutoWiredAs<MyDependency, IMyDependency>(); 

不過,這樣做的:

container.RegisterAs<MyDependency, IMyDependency>(); 

那麼有什麼區別?如果'自動佈線'找不到具體的實現,並且對是否可以解決需要依賴關係的服務沒有任何影響,那麼什麼是自動佈線?

Funq應該能夠按照慣例找到你的具體實現嗎?如果是這樣,那麼這個約定是什麼,如果不是同名的呢?

謝謝。

回答

4

對於這樣的簡單查詢,最好只聯繫源代碼,例如這裏是RegisterAutoWired的源代碼:

public IRegistration<T> RegisterAutoWired<T>() 
{ 
    var serviceFactory = GenerateAutoWireFn<T>(); 
    return this.Register(serviceFactory); 
} 

它產生在具體實現自動連線工廠。一個接口沒有實現,它需要是一個具體的類。

而對於RegisterAs的源代碼:

public IRegistration<TAs> RegisterAs<T, TAs>() where T : TAs 
{ 
    return this.RegisterAutoWiredAs<T, TAs>(); 
} 

這僅僅是一個更短的別名,你可以用它代替RegisterAutoWiredAs。

+0

所以,如果我理解正確此,我應該做的事情: container.RegisterAutoWired ();但是,如果我僅在運行時(當我使用依賴項調用服務時)執行此操作,則會得到「IMyDependency類型的所需依賴項無法解析」。所以我仍然不清楚這個方法的目的,因爲容器似乎無法找到與註冊的具體類型對應的接口。 – 2013-04-26 05:01:00

+3

這很簡單,只需要注入你註冊的內容,如果你註冊了而不是注入所有MyDependency屬性。如果你想要它注入'IMyDependency'屬性,而不是你需要調用'RegisterAs '。 – mythz 2013-04-26 05:23:51

+1

在我的項目中,我喜歡約200個類:MyClass:IMyClass。那麼根據這個每次我執行新類或刪除都可以爲它做佈線嗎? Unity,Windsor和StructureMap有自動裝配的習慣。 – nerijus 2015-03-11 09:42:17

8

您的意思是「我如何實現一個解決方案來搜索程序集並根據約定在ServiceStack IOC中自動註冊類?」

如果是的話,我會爲你提供一個解決方案:

  1. 創建你的注入,能夠類將實現一個接口。
  2. 讓您的可注入類實現該接口。
  3. 在引導程序代碼中使用反射來搜索您的程序集並獲取實現可注入接口的所有類的列表。
  4. 使用反射來根據您的約定獲取類名和接口。
  5. 調用ServiceStack IOC方法RegisterAutoWiredType並通過類和接口來註冊它們。

例如,如果我們的命名規則是類名IClassName:

private static void RegisterCustomTypes(Container container) 
{ 
    //Get the Assembly Where the injectable classes are located. 
    var assembly = Assembly.GetAssembly(typeof(IInjectable)); 

    //Get the injectable classes 
    var types =assembly.GetTypes() 
    .Where(m => m.IsClass && m.GetInterface("IInjectable") != null); 

    //loop through the injectable classes 
    foreach (var theType in types) 
    { 
    //set up the naming convention 
    var className = theType.Name; 
    var interfaceName = string.Concat("I", className); 
    //create the interface based on the naming convention 
    var theInterface = theType.GetInterface(interfaceName); 
    //register the type with the convention 
    container.RegisterAutoWiredType(theType, theInterface); 
    } 
} 

public interface IInjectable 
{ 

} 

//This class can be injected 
public interface ITestManager : IInjectable 
{ 
    void Execute(int id); 
} 

public class TestManager : ITestManager 
{ 
    public void Execute(int id) 
    { 
     throw new System.NotImplementedException(); 
    } 
} 
+0

由於我原來的文章,我已經明白,Func沒有內置彙編搜索。如果您按照此處的建議實施自己的反思,那麼您是否認爲在使用Func之後,諸如Ninject等其他解決方案會保留任何優勢(例如性能)? – 2013-10-16 23:30:26

+0

不確定。也許神話有一些指導呢? – 2013-10-18 14:14:11

+1

@Saber,DI僅在Web應用程序啓動時運行一次。在這裏可以忽略性能差異。溫莎或Ninject等等,他們都很好。我之所以使用Funq是因爲它帶有SS,我懶得維護另一個與SS包分離的IoC。 – Tom 2014-02-01 23:52:23