Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Validation Autofac注册验证_Validation_Dependency Injection_Inversion Of Control_Autofac - Fatal编程技术网

Validation Autofac注册验证

Validation Autofac注册验证,validation,dependency-injection,inversion-of-control,autofac,Validation,Dependency Injection,Inversion Of Control,Autofac,我正在为大型应用程序构建核心服务,我们从castle windsor切换到autofac。在使用assemly扫描和模块的自动注册方法中,一切正常,但我们有一个最新有趣的案例:一个接口有两个实现,autofac当然会以随机顺序注册它们,从业务角度来看,解决了错误的实现。当然,手动注册可以完成这项工作,但最好在IContainer级别上进行一些验证,至少将每个已注册服务的信息作为输出提供,如果它有多个实现,则应该将它们标记为默认值-这将在使用resolve请求容器时得到解决。其目的是当存在多个可用

我正在为大型应用程序构建核心服务,我们从castle windsor切换到autofac。在使用assemly扫描和模块的自动注册方法中,一切正常,但我们有一个最新有趣的案例:一个接口有两个实现,autofac当然会以随机顺序注册它们,从业务角度来看,解决了错误的实现。当然,手动注册可以完成这项工作,但最好在IContainer级别上进行一些验证,至少将每个已注册服务的信息作为输出提供,如果它有多个实现,则应该将它们标记为默认值-这将在使用resolve请求容器时得到解决。其目的是当存在多个可用的但保持自动注册时,强制开发人员注册特定的具体实现。
你找到解决这个问题的方法了吗?

公共静态类AutofacExtensions
public static class AutofacExtensions
{
    /// <summary>
    /// Checks if one implementation was chosen by developer for every interface
    /// </summary>
    /// <param name="container"></param>
    public static void ValidateRegistrations(this IContainer container)
    {
        if (container == null)
        {
            throw new ArgumentNullException(nameof(container));
        }

        var registrations = GetRegistrations(container);
        Validate(registrations);
    }

    static void Validate(IDictionary<Type, IList<Type>> registrations)
    {
        foreach (var registration in registrations.OrderBy(x => x.Key.FullName))
        {
            var unique = registration.Value.Distinct().Count();

            if (unique > 1)
            {
                var all = registration.Value.Count;

                if (all <= unique)
                {
                    var currentImplementations = registration.Value.Distinct().Select(x => x.FullName);
                    var aggregatedImplementations = string.Join(", ", currentImplementations);

                    throw new InvalidOperationException($"IoC/DI: for type '{registration.Key.FullName}' was not chose default implementation! Registered available implementations: {aggregatedImplementations}");
                }
            }
        }
    }

    static IDictionary<Type, IList<Type>> GetRegistrations(IContainer container)
    {
        var registrations = new Dictionary<Type, IList<Type>>();

        foreach (var registration in container.ComponentRegistry.Registrations)
        {
            foreach (var service in registration.Services.OfType<IServiceWithType>().Where(x => x.ServiceType.Namespace != null && x.ServiceType.Namespace.ToLowerInvariant().StartsWith("flb.")))
            {
                IList<Type> implementations;

                if (!registrations.TryGetValue(service.ServiceType, out implementations))
                {
                    implementations = new List<Type>();
                    registrations[service.ServiceType] = implementations;
                }

                implementations.Add(registration.Activator.LimitType);

            }
        }

        return registrations;
    }

}
{ /// ///检查开发人员是否为每个接口选择了一个实现 /// /// 公共静态无效验证注册(此IContainer容器) { if(容器==null) { 抛出新ArgumentNullException(nameof(container)); } var注册=GetRegistrations(容器); 验证(注册); } 静态无效验证(IDictionary注册) { foreach(registrations.OrderBy(x=>x.Key.FullName)中的var注册) { var unique=registration.Value.Distinct().Count(); 如果(唯一性>1) { var all=registration.Value.Count; 如果(全部x.全名); var aggregateImplements=string.Join(“,”,currentImplements); 抛出新的InvalidOperationException($“IoC/DI:对于类型“{registration.Key.FullName}”,未选择默认实现!已注册的可用实现:{AggregateImplements}”); } } } } 静态IDictionary GetRegistrations(IContainer容器) { var注册=新字典(); foreach(容器中的var注册.ComponentRegistry.Registrations) { foreach(registration.Services.OfType()中的var服务,其中(x=>x.ServiceType.Namespace!=null&&x.ServiceType.Namespace.ToLowerInvariant().StartsWith(“flb”)) { IList实现; if(!registrations.TryGetValue(service.ServiceType,out实现)) { 实现=新列表(); 注册[service.ServiceType]=实现; } Add(registration.Activator.LimitType); } } 申报注册; } }
今天,我向负责维护代码的github开发人员询问了同样的问题,但回答是“它不会包含在基本api中,因为它会对许多核心类产生影响”:(这里有一个提示,至少有两种方法可以构建简单的解决方案:一种是使用反射和访问私有结构和字段,另一种是使用官方api。做你必须做的事情,只要你理解你得到的信息可能不准确,原因如中所述。谢谢Travis,我已经准备好了som对IContainer的一个简单的扩展方法,它可以简单地计算注册数,对于简单的注册,它看起来很有效。我会让我的代码运行一段时间,看看它是否可以管理更复杂的注册。