2013-08-24 217 views
0

我有一個應用程序使用統一固件來解決對象。 我也做了一些變化框架並且可以作爲「新的變化」統一使用默認構造函數和參數化構造函數c#

包裝類看起來像

public static class ContractResolver 
{ 
     public static T Resolve<T>() //This is been used in many places in application 
     { 
      IUnityContainer container = new UnityContainer(); 
      var section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity"); 
      section.Containers.Default.Configure(container); 
      return container.Resolve<T>(); 
     } 

     //NEW CHANGE: This is the new function that suppose to return the instance of parameterised constructor 
     public static T Resolve<T>(ParameterOverride[] parameterOverrides) 
     { 
      IUnityContainer container = new UnityContainer(); 
      var section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity"); 
      section.Containers.Default.Configure(container); 
      return container.Resolve<T>(parameterOverrides); 
     } 
} 

的配置類似

代碼註釋中看到的類
<unity> 
    <containers> 
     <container> 
     <types> 
      <type type ="UnityTest.IImageRepositoryService, UnityTest" mapTo="UnityTest.ImageRepositoryService, UnityTest"/> 
     </types> 
     </container> 
    </containers> 
    </unity> 

的類和接口看起來像

public interface IImageRepositoryService 
{ 
    bool Exists(string imageName); 
} 

public class ImageRepositoryService : IImageRepositoryService 
{ 
    private readonly string mFilterName = "StandardImageFilter"; 

    //[InjectionConstructor] 
    public ImageRepositoryService() 
    { 
     DatabaseQueryProvider.Query("Image", mFilterName); 
    } 

    //NEW CHANGE. A CONSTRUCTOR THAT ACCEPTS A PARAMETER  
    //[InjectionConstructor] 
    public ImageRepositoryService(string filterName) 
    { 
     mFilterName = filterName; 
     DatabaseQueryProvider.Query("Image", filterName); 
    } 

    public bool Exists(string imageName) 
    { 
     Console.WriteLine("The image " + imageName + " found in filter " + mFilterName); 
     return true; 
    } 

} 

的使用看起來像

var serviceDefault = ContractResolver.Resolve<IImageRepositoryService>(); 
serviceDefault.Exists("myimage.bmp"); 

新的變化打破了舊用法。即

var serviceDefault = ContractResolver.Resolve<IImageRepositoryService>(); 

拋出異常 分辨率依賴性的失敗,類型= 「UnityTest.IImageRepositoryService」,名字= 「(無)」。 發生異常時:解析時。 異常是:InvalidOperationException - 無法構造字符串類型。您必須配置容器以提供此值。

我想在新功能的同時不想打破舊功能。

var serviceDefault = ContractResolver.Resolve<IImageRepositoryService>(); 
serviceDefault.Exists("myimage.bmp"); 

應該顯示

var parameterOverride1 = new ParameterOverride("filterName", "filter1"); 
var servicefilter1 = ContractResolver.Resolve<IImageRepositoryService>(new[] { parameterOverride1 }); 
servicefilter1.Exists("myimage.bmp"); 

應顯示在控制檯的消息「圖像myimage.bmp在濾波器過濾器1中發現」,「在濾波器StandardImageFilter中發現的圖像myimage.bmp」在控制檯消息

var parameterOverride2 = new ParameterOverride("filterName", "filter2"); 
var servicefilter2 = ContractResolver.Resolve<IImageRepositoryService>(new[] { parameterOverride2 }); 
servicefilter2.Exists("myimage.bmp"); 

應該顯示

0123「在過濾器過濾器2中發現的圖像myimage.bmp」在控制檯消息

如何解決這個問題?

回答

1

如果您想解析相同類型(本例中爲IImageRepositoryService),但對Resolve調用不同的構造函數有不同的調用,那麼您將需要使用指定的註冊。

在你的情況,你可以在XML配置做到這一點:

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity"> 
    <container> 
    <register type ="UnityTest.IImageRepositoryService, UnityTest" mapTo="UnityTest.ImageRepositoryService, UnityTest"> 
     <constructor /> 
    </register> 
    <register name="ParameterizedRepository" 
       type="UnityTest.IImageRepositoryService, UnityTest" 
       mapTo="UnityTest.ImageRepositoryService, UnityTest"> 
     <constructor> 
     <param name="filterName" value="dummyValue" /> 
     </constructor> 
    </register> 
    </container> 
</unity> 

請注意,我已經使用了統一2(3)配置風格。

因此,這告訴Unity,解析時使用名稱「ParameterizedRepository」來調用名爲「filterName」的參數的構造函數。我在這裏所用空值,因爲我們將反正覆蓋在運行時的值:

var imageRepositoryService = container.Resolve<IImageRepositoryService>(
    "ParameterizedRepository", 
    new ParameterOverride("filterName", "filter2")); 

所以這就是如何得到你想要使用什麼團結,在你的包裝類的術語,你應該添加一個名稱參數:

public static class ContractResolver 
{ 
    //NEW CHANGE: This is the new function that suppose to return the instance of parameterised constructor 
    public static T Resolve<T>(string name, params ParameterOverride[] parameterOverrides) 
    { 
     IUnityContainer container = new UnityContainer(); 
     var section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity"); 
     section.Containers.Default.Configure(container); 
     return container.Resolve<T>(name, parameterOverrides); 
    } 
} 

一些不請自來的意見(在嘗試的精神是有幫助的):

  • 它看起來像您使用統一版本1.如果是這樣,你可能要考慮升級(最近發佈版本3),如果您不使用Unity版本1,則可能需要考慮更改XML配置語法以使用更新的方法以及使用LoadConfiguration()擴展方法。

  • 我不知道爲什麼每次打電話給ContractResolver.Resolve()都會創建一個新的Unity容器,然後加載配置。這可能會對性能造成一定影響。通常,您將創建一個容器並加載一次配置,並在應用程序的整個生命週期中使用該實例。

  • 我可以理解你會如何試圖隱藏ContractResolver後面的容器實現,但是增加了ParameterOverride(這是Unity特有的),抽象變得有點泄漏。