2013-08-24 64 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特有的),抽象变得有点泄漏。