首页 > 解决方案 > Unity 多接口实现按约定注册

问题描述

我正在尝试按照惯例注册单个接口的多个实现,然后将所有这些接口用作其他类中的依赖项。不幸的是,我在尝试这样做时遇到了一些问题。

我想注册多个实现,所以我添加了WithName.TypeNamedruing 注册,但这似乎引起了问题。没有它,我无法为单个接口注册多个实现。

以下是不起作用的简单示例。Unity 抛出异常,我不知道为什么。

Unity.ResolutionFailedException:'解决失败并出现错误:没有公共构造函数可用于类型 KYPClient.IConf。

namespace KYPClient
{
public interface IConf
{
    string conf();
}

public class Conf : IConf
{
    public string conf()
    {
        return "conf";
    }
}

public interface ILoader
{
    string load();
}

public class Load_1 : ILoader
{
    public string load()
    {
        return "load-1";
    }
}

public class Load_2 : ILoader
{
    public string load()
    {
        return "load-2";
    }
}

public class MainCls
{
    private IConf _conf;
    private IEnumerable<ILoader> _loaders;

    public MainCls(IConf conf, IEnumerable<ILoader> loaders)
    {
        _conf = conf;
        _loaders = loaders;
    }

    public void Run()
    {
        System.Console.WriteLine(_conf.conf());
        foreach (var l in _loaders)
        {
            Console.WriteLine(l.load());
        }
    }
}


internal static class Client
{
    private static void Main()
    {   
        using var container = new UnityContainer();

        container.RegisterTypes(
            AllClasses.FromAssemblies(typeof(MainCls).Assembly),
            WithMappings.FromAllInterfaces,
            WithName.TypeName,
        WithLifetime.ContainerControlled);

        var main = container.Resolve<MainCls>();

        main.Run();
    }
}

}

标签: c#.netunity-containerregistration

解决方案


问题是您正在使用该WithName.TypeName选项。这意味着程序集中的每种类型都是作为容器中的命名注册完成的。在您的情况下这是一件好事,因为您正在注册多个ILoader实例,因此容器必须能够区分它们。但是,这也意味着当它被解析时,您必须传递名称才能让容器找到它。

换句话说,当容器看到构造函数时public MainCls(IConf conf, IEnumerable<ILoader> loaders),它会将其解释为“IConf使用默认名称注入实例”,这在您的容器中不存在。IConf的注册名称为“Conf”(或者可能是“KYPClient.Conf”,我不确定,因为我从未使用过该RegisterTypes方法)。

因此,您必须在构造函数中明确命名它。此外,根据如何配置 Unity 为 IEnumerable 注入数组,您需要一个数组来获取所有已注册的ILoader类型。

public MainCls([Dependency("Conf")] IConf conf, ILoader[] loaders)

当然,使用命名依赖项有一些缺点(例如,如果重构和重命名类会发生什么情况)。看看With Unity 如何将命名依赖项注入构造函数的第二个答案?使用工厂模式的策略。


推荐阅读