Vac*_*ano 67 c# inversion-of-control unity-container
我IRespository
在以下代码中注册了两次(带名字):
// Setup the Client Repository
IOC.Container.RegisterType<ClientEntities>(new InjectionConstructor());
IOC.Container.RegisterType<IRepository, GenericRepository>
("Client", new InjectionConstructor(typeof(ClientEntities)));
// Setup the Customer Repository
IOC.Container.RegisterType<CustomerEntities>(new InjectionConstructor());
IOC.Container.RegisterType<IRepository, GenericRepository>
("Customer", new InjectionConstructor(typeof(CustomerEntities)));
IOC.Container.RegisterType<IClientModel, ClientModel>();
IOC.Container.RegisterType<ICustomerModel, CustomerModel>();
Run Code Online (Sandbox Code Playgroud)
但是当我想要解决这个问题(使用IRepository
)时,我必须像这样做一个手动解决方案:
public ClientModel(IUnityContainer container)
{
this.dataAccess = container.Resolve<IRepository>(Client);
.....
}
Run Code Online (Sandbox Code Playgroud)
我想要做的是在构造函数中解析它(就像IUnityContainer
).我需要一些方法来说明要解析的命名类型.
这样的事情:( 注意:不是真正的代码)
public ClientModel([NamedDependancy("Client")] IRepository dataAccess)
{
this.dataAccess = dataAccess;
.....
}
Run Code Online (Sandbox Code Playgroud)
有没有办法让我的假代码工作?
Chr*_*res 87
您可以在API,属性或配置文件中配置带或不带名称的依赖项.你没有提到上面的XML,所以我假设你正在使用API.
要告诉容器解析命名依赖项,您需要使用一个InjectionParameter
对象.为您的ClientModel
示例,请执行以下操作:
container.RegisterType<IClientModel, ClientModel>(
new InjectionConstructor( // Explicitly specify a constructor
new ResolvedParameter<IRepository>("Client") // Resolve parameter of type IRepository using name "Client"
)
);
Run Code Online (Sandbox Code Playgroud)
这告诉容器"在解析时ClientModel
,调用带有单个IRepository
参数的构造函数.在解析该参数时,除了类型之外,还要使用名称'Client'解析."
如果您想使用属性,您的示例几乎可以工作,您只需要更改属性名称:
public ClientModel([Dependency("Client")] IRepository dataAccess)
{
this.dataAccess = dataAccess;
.....
}
Run Code Online (Sandbox Code Playgroud)
Tch*_*uan 24
这是一个非常晚的回复,但问题仍然出现在谷歌.
所以无论如何,5年后......
我有一个非常简单的方法.通常当你需要使用"命名依赖"时,这是因为你试图实现某种策略模式.在这种情况下,我只是在Unity和我的其余代码之间创建一个间接级别,称为StrategyResolver
不直接依赖Unity.
public class StrategyResolver : IStrategyResolver
{
private IUnityContainer container;
public StrategyResolver(IUnityContainer unityContainer)
{
this.container = unityContainer;
}
public T Resolve<T>(string namedStrategy)
{
return this.container.Resolve<T>(namedStrategy);
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
public class SomeClass: ISomeInterface
{
private IStrategyResolver strategyResolver;
public SomeClass(IStrategyResolver stratResolver)
{
this.strategyResolver = stratResolver;
}
public void Process(SomeDto dto)
{
IActionHandler actionHanlder = this.strategyResolver.Resolve<IActionHandler>(dto.SomeProperty);
actionHanlder.Handle(dto);
}
}
Run Code Online (Sandbox Code Playgroud)
注册:
container.RegisterType<IActionHandler, ActionOne>("One");
container.RegisterType<IActionHandler, ActionTwo>("Two");
container.RegisterType<IStrategyResolver, StrategyResolver>();
container.RegisterType<ISomeInterface, SomeClass>();
Run Code Online (Sandbox Code Playgroud)
现在,关于这一点的好处是,在将来添加新策略时,我永远不会再次触及StrategyResolver.
这很简单.非常干净,我将Unity的依赖性保持在最低限度.我唯一一次接触StrategyResolver是因为我决定改变容器技术,这是不太可能发生的.
希望这可以帮助!
编辑:我真的不喜欢接受的答案,因为当你Dependency
在服务的构造函数中使用该属性时,你实际上对Unity有很强的依赖性.该Dependency
属性是Unity库的一部分.那时你不妨IUnityContainer
到处传递依赖.
我更喜欢让我的服务类依赖于我完全拥有的对象,而不是在整个地方都依赖于外部库.使用Dependency
属性也使构造函数签名不那么干净和简单.
此外,此技术允许在运行时解析命名依赖项,而无需在构造函数,应用程序配置文件或使用中对命名依赖项进行硬编码,InjectionParameter
这些都是需要知道在设计时使用什么命名依赖项的方法.
编辑(2016年9月19日):对于那些可能会问,容器将知道通过自己当您请求IUnityContainer
的依赖,如图所示StrategyResolver
构造函数签名.
编辑(2018-10-20):这是另一种方式,只需使用工厂:
public class SomeStrategyFactory : ISomeStrategyFactory
{
private IStrategy _stratA;
private IStrategy _stratB;
public SomeFactory(IStrategyA stratA, IStrategyB stratB)
{
_stratA = stratA;
_stratB = stratB;
}
public IStrategy GetStrategy(string namedStrategy){
if (namedStrategy == "A") return _stratA;
if (namedStrategy == "B") return _stratB;
}
}
public interface IStrategy {
void Execute();
}
public interface IStrategyA : IStrategy {}
public interface IStrategyB : IStrategy {}
public class StrategyA : IStrategyA {
public void Execute(){}
}
public class StrategyB : IStrategyB {
public void Execute() {}
}
Run Code Online (Sandbox Code Playgroud)
用法:
public class SomeClass : ISomeClass
{
public SomeClass(ISomeStrategyFactory strategyFactory){
IStrategy strat = strategyFactory.GetStrategy("HelloStrategy");
strat.Execute();
}
}
Run Code Online (Sandbox Code Playgroud)
注册:
container.RegisterType<ISomeStrategyFactory, SomeStrategyFactory>();
container.RegisterType<IStrategyA, StrategyA>();
container.RegisterType<IStrategyB, StrategyB>();
container.RegisterType<ISomeClass, SomeClass>();
Run Code Online (Sandbox Code Playgroud)
第二个建议是相同的,但使用工厂设计模式.
希望这可以帮助!