C# 使用Unity如何将命名依赖项注入构造函数?
我在以下代码中注册了两次C# 使用Unity如何将命名依赖项注入构造函数?,c#,inversion-of-control,unity-container,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(typeo
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>();
我想做的是在构造函数中解析它(就像IUnityContainer
)。我需要一些方法来说明要解析的命名类型
类似这样的内容:(注意:不是真正的代码)
有没有办法让我的伪代码正常工作?您应该能够使用参数覆盖
var repository = IOC.Container.Resolve<IRepository>("Client");
var clientModel = IOC.Container.Resolve<ClientModel>(new ParameterOverrides<ClientModel> { {"dataAccess", repository } } );
var repository=IOC.Container.Resolve(“客户机”);
var clientModel=IOC.Container.Resolve(新参数覆盖{{“dataAccess”,repository});
编辑:
我不知道你为什么要传递UnityContainer——就我个人而言,我们将依赖项注入构造函数本身(这在我看来是“正常的”)。但无论如何,您可以在RegisterType和Resolve方法中指定名称
IOC.Container.RegisterType<IRepository, GenericRepository>("Client");
IOC.Container.Resolve<IRepository>("Client");
IOC.Container.RegisterType(“客户端”);
IOC.Container.Resolve(“客户”);
它将为您提供为该名称注册的类型。您可以在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"
)
);
这是一个非常晚的回答,但这个问题仍然出现在谷歌 所以不管怎样,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);
}
}
用法:
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);
}
}
public class SomeClass : ISomeClass
{
public SomeClass(ISomeStrategyFactory strategyFactory){
IStrategy strat = strategyFactory.GetStrategy("HelloStrategy");
strat.Execute();
}
}
注册:
container.RegisterType<IActionHandler, ActionOne>("One");
container.RegisterType<IActionHandler, ActionTwo>("Two");
container.RegisterType<IStrategyResolver, StrategyResolver>();
container.RegisterType<ISomeInterface, SomeClass>();
container.RegisterType<ISomeStrategyFactory, SomeStrategyFactory>();
container.RegisterType<IStrategyA, StrategyA>();
container.RegisterType<IStrategyB, StrategyB>();
container.RegisterType<ISomeClass, SomeClass>();
container.RegisterType();
container.RegisterType();
container.RegisterType();
container.RegisterType();
第二个建议是相同的,但使用工厂设计模式
希望这有帮助 不要这样做-只需创建一个
类ClientRepository:GenericRepository{}
并使用类型系统。这会起作用,但这意味着了解clientModel的级别还需要知道存储库是什么以及它的外观。我需要将存储库从了解“clientModel”的级别抽象出来。(事实上,clientModel的全部目的是将存储库抽象到我的服务层。我想直接注入构造函数中。(这就是这个问题的重点。)。我只有2个IRepository映射。我正在寻找一种方法来帮助unity区分它们。@Kyle-在resolve调用中指定名称是不可传递的-Resolution不会自动解析。容器中需要配置才能使用正确的名称。是否可以在没有dependency属性的情况下使其工作?F或示例IRepository>(“客户”)
应该使用API注入到另一个ClientModel
@Legends实例中。为所需注入样式的每个变体为ClientModel创建单独的命名注册,然后解决对IClientModel的依赖关系。其工作原理与上面对IRepository的工作原理相同。我更喜欢此模式而不是InjectionConstruct或者,它不是隐藏在StrategyResolver后面的服务定位器吗?它看起来确实像某种形式的服务定位器,但我还是认为它不是。你只是将StrategyResolver用作实现策略模式的助手。StrategyResolver不是你的依赖注入容器。如果你开始做一些不正常的事情作为命名依赖项加载所有依赖项,并使用StrategyResolver查找它们,那么是的,在这种情况下,您实际上只是将其用作服务定位器反模式。如果您不滥用并坚持其目的,那么它将使您的代码美观,而不依赖您的DI技术。StrategyResolver注册为de容器中的依赖项。依赖项通过构造函数注入。如果当前类已在容器中注册,则容器将能够通过查看类构造函数参数来注入所需的依赖项。对此的改进(以限制误用)可以是限制IStrategyResolver接口。基本上,您不需要解析任何T
,而只需要一个方法IActionHandler ResolveMyStrategy(string strategyName).
My two Second…我已经按照这些思路实现了一些东西,但是我没有将IUnityContainer
传递给解析器类型,而是使用了Func resolver
作为构造函数参数。因此,您可以将解析委托给DI项目模块,因此不知道所使用的容器。注册:contaRegisterInstance(新的StrategyResolver(key=>container.Resolve(key)))
。此外,这种方法对可能的服务定位器误用限制更大。
container.RegisterType<IActionHandler, ActionOne>("One");
container.RegisterType<IActionHandler, ActionTwo>("Two");
container.RegisterType<IStrategyResolver, StrategyResolver>();
container.RegisterType<ISomeInterface, SomeClass>();
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() {}
}
public class SomeClass : ISomeClass
{
public SomeClass(ISomeStrategyFactory strategyFactory){
IStrategy strat = strategyFactory.GetStrategy("HelloStrategy");
strat.Execute();
}
}
container.RegisterType<ISomeStrategyFactory, SomeStrategyFactory>();
container.RegisterType<IStrategyA, StrategyA>();
container.RegisterType<IStrategyB, StrategyB>();
container.RegisterType<ISomeClass, SomeClass>();