2016-06-10 29 views
0

我有兩個獨立的項目...一個項目使用Simple Injector和另一個Unity。從簡單的注入項目中,我嘗試使用Unity爲其DI註冊位於項目中的類的接口/實現。我可以成功地做到這一點並獲得對課程的訪問權限,但在該課程中標記爲Unity [依賴項]的任何內容都無法解析。我可以將這些依賴項註冊到Simple Injector容器,但是一旦使用Unity進入課程,它就會失去它。依賴注入 - 如何在實現使用Unity for DI時使用簡單注入器注入接口的實現

實施例:

PROJECT1(使用簡單注射器)

public class StartUp { 
    var container = new Container(); 
    container.RegisterSingleton(typeof(IGenericRepo<>), typeof(GenericRepo)); 
    container.RegisterSingleton<IService, Service>(); 
    //more code below etc... 
} 

public class TestController 
{ 
    private readonly IService service; 

    public TestController(IService service) 
    { 
     this.service = service; 
    } 

    public void TestMethod() 
    { 
     var test = service.GetEverything(); 
    } 
} 

Project2的(使用Unity)

public class Service : IService 
{ 
    [Dependency] 
    public IGenericRepo<ServiceObj> _serviceRepo { private get; set; } 

    public IQueryable<ServiceObj> GetEverything() 
    { 
     return _serviceRepo.Get(); 
    } 
} 

通過以上的例子中,我能到GetEverything方法在Project 2中,但是_serviceRepo依賴性爲空。有沒有辦法讓它知道從Project1使用註冊的GenericRepo <>?

這可能嗎?

謝謝! Ryan

+0

你在哪裏註冊你的serviceRepo在項目二?請參閱:https://msdn.microsoft.com/en-us/library/dn178463(v=pandp.30).aspx – kmac

+0

Project2目前沒有明確註冊任何東西...目前使用的唯一其他項目有在其他Unity項目中,在web.config中完成註冊或者在應用程序中顯式地使用容器。 – Contissi

+0

您可能能夠將第一個項目dll包含在第二個項目的引用中,然後進行註冊。 – kmac

回答

1

如果我理解正確項目2是一些共享項目,在其他使用Unity進行依賴注入的項目中使用。 Unity在這種情況下使用屬性注入通過使用DependencyAttribute註釋屬性。

簡單的注射器是能夠做屬性注入。然而,屬性注入只能用於可選的依賴關係。當你遇到NullReferenceException這個依賴不是可選的!

所以你應該將IGenericRepo<ServiceObj>移動到IService的構造函數。這使得IService的用戶清楚它需要存儲庫才能正常工作。當你將單元測試IService時,這將變得特別有用,因爲在這種情況下,構造函數將清楚地表明它需要一個存儲庫。

通過將依賴關係移至構造函數簡單注入器將正確注入存儲庫或在配置無效時拋出ActivationException

你可以測試,我建議你這樣做,通過撥打container.Verify(),你可以在這裏閱讀:Verify the container’s configuration。這將使申請到fail fast

如果項目2不能被重構或其他一些令人信服的原因構造函數注入不是一個選項,Simple Injector確實支持屬性注入。但它並不支持這種開箱即用的方式。簡單注射器的設計原理之一是to never fail silently,因此建議僅使用Explicit property injection。如果配置無效,這將使容器有機會使用其Diagnostic Services並快速失敗。

正如你所引用的文檔中閱讀,也有做房地產注射2種方式:

  1. 通過註冊與呼叫的初始化器 container.RegisterInitializer()
  2. 通過實施IPropertySelectionBehavior

選項2將讓Simple Injector自動使用Diagnostics Services檢查相關性。在驗證所有'初始化器'時也執行,但lambda中的代碼沒有檢查生活方式等。

簡單的注射器不鼓勵它的用戶依賴容器,因此它不包含任何Atrributes其中您可以使用開箱即用的方式,例如Unity擁有DependencyAttribute

所以,你有兩個選擇在這裏:

  1. 讓Project 1還採取統一(這間接已經擁有!呸)的依賴,創造IPropertySelectionBehavior實現搜索的統一DependencyAttribute
  2. 在項目2中創建您自己的自定義Attribute並註釋_serviceRepo,這也是該自定義屬性。

1和2之間的唯一區別是搜索哪個屬性。 如果您不能觸摸項目2,則無法使用選項2。實施IPropertySelectionBehavior很簡單:

// custom attribute only for option 1 
public class ImportAttribute : Attribute { } 

class UnityDependencyPropertySelectionBehavior : IPropertySelectionBehavior 
{ 
    public bool SelectProperty(Type type, PropertyInfo prop) 
    { 
     return prop.GetCustomAttributes(typeof(DependencyAttribute)).Any(); 
    } 
} 

您可以使用此自定義IPropertySelectionBehavior配置容器:

container.Options.PropertySelectionBehavior = 
       new UnityDependencyPropertySelectionBehavior(); 

總結: 移動依賴於構造,因爲它不是一個可選的依賴。換句話說使用構造函數注入! 如果有令人信服的理由不這樣做IPropertySelectionBehavior