[英]Using default constructor and parameterised constructor in unity c#
我有一个使用统一固件来解析对象的应用程序。 我对框架和类做了一些更改,可以在代码注释中将其视为“ NEW CHANGE”
包装器类看起来像
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-无法构造类型String。 您必须配置容器以提供该值。
我想同时拥有新功能,不想破坏旧功能。
var serviceDefault = ContractResolver.Resolve<IImageRepositoryService>();
serviceDefault.Exists("myimage.bmp");
应该在控制台中显示消息“在过滤器StandardImageFilter中找到图像myimage.bmp”
var parameterOverride1 = new ParameterOverride("filterName", "filter1");
var servicefilter1 = ContractResolver.Resolve<IImageRepositoryService>(new[] { parameterOverride1 });
servicefilter1.Exists("myimage.bmp");
应该在控制台中显示消息“在过滤器filter1中找到图像myimage.bmp”
var parameterOverride2 = new ParameterOverride("filterName", "filter2");
var servicefilter2 = ContractResolver.Resolve<IImageRepositoryService>(new[] { parameterOverride2 });
servicefilter2.Exists("myimage.bmp");
应该在控制台中显示消息“在过滤器filter2中找到图像myimage.bmp”
如何解决这个问题?
如果要解析相同的类型(在本例中为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>
注意,我已经使用了Unity 2(和3)配置样式。
因此,这告诉Unity,在解析时使用名称“ ParameterizedRepository”来调用名为“ filterName”的参数的构造函数。 我在这里使用了一个虚拟值,因为无论如何我们将在运行时覆盖该值:
var imageRepositoryService = container.Resolve<IImageRepositoryService>(
"ParameterizedRepository",
new ParameterOverride("filterName", "filter2"));
这就是使用Unity获得所需内容的方法,因此对于包装器类,您应该添加一个name参数:
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);
}
}
一些不请自来的评论(本着试图有所帮助的精神):
看起来您正在使用Unity版本1。如果是,则可能要考虑升级(版本3是最近发布的),如果您没有使用Unity版本1,则可能要考虑更改XML配置语法以使用Unity版本1。更新的方法以及使用LoadConfiguration()
扩展方法。
我不确定为什么每次对ContractResolver.Resolve()
调用都会创建一个新的Unity容器,然后加载配置。 这可能会影响性能。 通常,您将创建一个容器并加载一次配置,并在应用程序的生存期内使用该实例。
我可以理解如何将容器实现隐藏在ContractResolver
后面,但是通过添加ParameterOverride
(Unity特定),抽象变得有点漏水。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.