1

我想用Unity來做一些依賴注入與一些交叉類。現在我有一些緩存基礎設施,我已經包裝了MS企業庫。我正在包裝它,因爲我可能想在以後使用其他東西。此外,我可能想混合並匹配不同的緩存存儲。Unity注入問題傳遞信息到多個圖層

所以我有一個通用的緩存接口和一個具體實現如下

public interface ICacheProvider 
{ 
    void Add(object key, object value); 

    void Remove(object key); 

    object GetData(object key); 

    void Flush(); 
} 

public class MyCacheProvider : ICacheProvider 
{ 
    private ICacheManager cacheManager; 

    public MyProvider(ICacheManager manager) 
    { 
     cacheManager = manager; 
    } 
} 

的的ICacheManager是企業庫的類型。我想要做的是在運行時使用unity來解析緩存管理器。此外,對於不同的cacheStore,這可能會有所不同。現在,他們都解決了我顯示的類型。這是我的統一配置。

<unity> 
<typeAliases> 
    <typeAlias alias="string" type="System.String, mscorlib" /> 
    <typeAlias alias="ICacheProvider" type="DomainBase.Caching.ICacheProvider, DomainBase" /> 
    <typeAlias alias="MSCacheProvider" type="Caching.MyCacheProvider, Caching" /> 
</typeAliases> 
<containers> 
    <container> 
    <types> 
     <register type="ICacheProvider" mapTo="MSCacheProvider" /> 
    </types> 
    </container> 
</containers> 

下面是如何設置我統一容器:

private IUnityContainer rootContainer; 

rootContainer = new UnityContainer().LoadConfiguration(); 
var configurator = new UnityContainerConfigurator(rootContainer); 
EnterpriseLibraryContainer.ConfigureContainer(configurator, ConfigurationSourceFactory.Create()); 

這使得企業庫自動從配置獲取信息和解決基於那裏的東西。問題是,當我深入兩層時(即,我沒有直接解析企業庫接口),解析失敗,因爲我沒有命名解析。考慮到企業庫擴展,命名解析不是必需的,因爲提供的擴展註冊了正確的解析,就好像它被命名一樣。儘管如此,我收集Unity無法通過將我的界面映射到企業庫來實現自己的魔術飛躍。下面是一些示例代碼

//note that's ICacheProvider which my interface for abstracting caching. NOT 
//the enterprise library interface 
ICacheProvider customersCache = rootContainer.Resolve<ICacheProvider>(); //works 
ICacheProvider productsCache = rootContainer.Resolve<ICacheProvider>("ProductsCache"); //doesn't work 

第一個樣品的作品,因爲有默認的分辨率,但是因爲我沒有對「產品」命名的分辨率第二樣品失敗。有沒有一種處理這種情況的好方法?我不想爲添加到系統中的每個不同的緩存存儲區命名解析,因爲它們已經在緩存配置中定義。我會嘗試一種不同類型的注入,但在這種情況下你幾乎不得不使用構造函數注入。

此外,我已經嘗試明確定義命名註冊,即使定義了兩個單獨的CacheManager實例,我仍然會得到相同的CacheManager實例。我想,一旦初始化的解決方案完成,它會查看構造函數,並且沒有「名稱」,只是基於默認值注入?

感謝您的幫助

回答

1

找到了答案,以我自己的問題。我能想出的唯一方法是使用自定義擴展並檢查類型。下面是一個樣本

public class WrappedResolver : UnityContainerExtension 
{ 

    protected override void Initialize() 
    { 
     this.Context.Strategies.Add(new WrappedBuilder(this.Container), Microsoft.Practices.Unity.ObjectBuilder.UnityBuildStage.PreCreation); 

    } 
} 

public class WrappedBuilder : BuilderStrategy 
{ 
    IUnityContainer baseContainer; 

    public WrappedBuilder(IUnityContainer container) 
    { 
     baseContainer = container; 
    } 

    public override void PreBuildUp(IBuilderContext context) 
    { 

     if (context.BuildKey.Type.Name.Contains("ICacheProvider") && context.OriginalBuildKey.Name != null) 
     { 
      string originalName = context.OriginalBuildKey.Name; 
      Type mytype = Type.GetType("Microsoft.Practices.EnterpriseLibrary.Caching.ICacheManager, Microsoft.Practices.EnterpriseLibrary.Caching"); 
      Type originalType = context.BuildKey.Type;// Type.GetType("DomainBase.Caching.ICacheProvider, DomainBase"); 
      context.Existing = baseContainer.Resolve(originalType, new ParameterOverride("manager", 
                     new ResolvedParameter(mytype, originalName))); 

      context.BuildComplete = true; 

     } 
     base.PreBuildUp(context); 
    } 
}