如何使用Unity解决接口集合?

时间:2015-11-06 20:46:51

标签: c# unity-container

我有一个带有构造函数的类,它接受一个子接口的集合

public class Manager : IManager
{
   public Manager(IEnumerable<IDataAccess> dataAccess)
   {

IDataAccess是一个基本界面

public interface IFooDataAccess : IDataAccess
{

public interface IBarDataAccess : IDataAccess
{

public interface IBazDataAccess : IDataAccess
{

每种方法都有具体的实施方案。 当我解析IManager时,我希望使用FooDataAccess,BarDataAccess和BazDataAccess的集合填充dataAccess参数。

我使用unity作为IoC,目前的注册是:

    public static void RegisterTypes(IUnityContainer container)
    {
        container.RegisterTypes(AllClasses.FromAssemblies(
                typeof(IManager).Assembly),
            WithMappings.FromMatchingInterface,
            WithName.Default,
            WithLifetime.ContainerControlled);

我在解决方案中也有其他几个类(因此使用注册模式),所以我想保留它。我一直在努力尝试在其上注册IManager:

        var allDataAccesses = container.ResolveAll<IDataAccess>();
        var parameter = new InjectionConstructor(allDataAccesses);
        container.RegisterType<IManager, Manager>(parameter);

但我无法让它发挥作用,我错过了什么。如何配置unity以解析构造函数?

1 个答案:

答案 0 :(得分:4)

您所做的注册将映射直接实现的接口,而不是IDataAccess

例如,它会将IFooDataAccess映射到FooDataAccess。您需要的是将IDataAccess映射到FooDataAccess,例如。

要解决此问题,请添加以下注册码:

container.RegisterTypes(
    typeof (IManager)
        .Assembly
        .GetTypes()
        .Where(x => x.IsClass)
        .Where(x => typeof (IDataAccess).IsAssignableFrom(x)),
    x => new[] {typeof (IDataAccess)},
    WithName.TypeName, WithLifetime.ContainerControlled);

这将在程序集中搜索实现IDataAccess(直接或间接)的类,并将在IDataAccess和这些类之间创建一个映射。

这里需要注意的一件重要事情是,它为注册命名。这很重要,因为如果您将接口IDataAccess映射到许多类,则无法使用默认名称。团结将如何知道要使用哪个地图条目?

您需要做的另一件事是将IEnumerable<IDataAccess>映射到IDataAccess[],如下所示:

container.RegisterType<IEnumerable<IDataAccess>, IDataAccess[]>();

Unity知道如何通过查看所需接口的命名注册来解析数组。默认情况下,IEnumerable<T>不能执行相同的操作。另一种方法是更改​​构造函数以使用如下数组:

public class Manager : IManager
{
    public Manager(IDataAccess[] dataAccess)
    {
        ....
    }

    ....
}