如何使用Unity IoC在运行时选择已注册的从属类型?

时间:2015-03-26 02:16:54

标签: c# dependency-injection unity-container

我是Unity的新手,我无法解析正确的对象。

我有一个CustomerManager类,它作为依赖IDataAccess。

的CustomerManager

public class CustomerManager
{
    private IDataAccess dataAccess;

    public CustomerManager(IDataAccess dataAccess)
    {
        this.dataAccess = dataAccess;
    }

    public Customer GetCustomer(int id)
    {
        return this.dataAccess.GetCustomer(id);
    }

    public void SaveCustomer(Customer customer)
    {
        this.dataAccess.SaveCustomer(customer);
    }
}

IDataAccess

public interface IDataAccess
{
    void SaveCustomer(Customer customer);
    Customer GetCustomer(int id);
}

我有两个实现IDataAccess的类,名为SQLServerDataAccess和MongoDataAccess。

我要做的是注册实现IDataAccess的类,然后使用Resolve创建CustomerManager的实例。

这是我的注册:

UnityIoC.Instance.RegisterType<IDataAccess,SQLServerDataAccess>("SQL");
UnityIoC.Instance.RegisterType<IDataAccess,MongoDataAccess>("Mongo");

当我尝试直接解析IDataAccess类的实例时,它可以正常工作。

IDataAccess dataAccess = UnityIoC.Instance.Resolve<IDataAccess>("Mongo");

但是,当我尝试解析CustomerManager时,我得到一个例外。

我这样做:

CustomerManager manager = UnityIoC.Instance.Resolve<CustomerManager>();

我收到以下异常:

Resolution of the dependency failed, type = "UnityIoCExample.CustomerManager", name = "(none)".

Exception occurred while: while resolving.

Exception is: InvalidOperationException - The current type, UnityIoCExample.IDataAccess, is an interface and cannot be constructed. Are you missing a type mapping?

-----------------------------------------------

At the time of the exception, the container was:
Resolving UnityIoCExample.CustomerManager,(none)

Resolving parameter "dataAccess" of constructor UnityIoCExample.CustomerManager(UnityIoCExample.IDataAccess dataAccess)

Resolving UnityIoCExample.IDataAccess,(none)

我很清楚,异常是由Unity不知道IDataAccess的注册类型用作CustomerManager的依赖项引起的,但我无法弄清楚如何指定。我这样做大多是正确的,只是缺少一件或者我离开了?

我唯一的想法是在解析CustomerManager时使用ParameterOverride并使用该参数解析CustomerManager内的IDataAccess。

修改后的CustomerManager构造函数:

public CustomerManager(string dbType)
{
    this.dataAccess = UnityIoC.Instance.Resolve<IDataAccess>(dbType);
}

解决CustomerManager

CustomerManager manager = UnityIoC.Instance.Resolve<CustomerManager>(new ParameterOverride("dbType", "Mongo"));

我不确定这是不是最好的做法。

1 个答案:

答案 0 :(得分:2)

您需要在所描述的方案中使用InjectionContructor。

UnityIoC.Instance.RegisterType<IDataAccess,SQLServerDataAccess>("SQL");
UnityIoC.Instance.RegisterType<IDataAccess,MongoDataAccess>("Mongo");

UnityIoC.Instance.RegisterType<CustomerManager,CustomerManager>("Mongo", new InjectionConstructor(new ResolvedParameter<IDataAccess>("Mongo")));

UnityIoC.Instance.RegisterType<CustomerManager,CustomerManager>("SQL", new InjectionConstructor(new ResolvedParameter<IDataAccess>("SQL")));

CustomerManager manager = UnityIoC.Instance.Resolve<CustomerManager>();

为了让这个类整齐一些,可以将它提取到自己的DIConfig类中。这些InjectionConstructors中的几个将是可重用的,并且在类中提取将有助于此。