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>();