c# - 列出依赖解析器 DefaultConstructorFinder 的所有缺失的 Autofac 注册

标签 c# asp.net-web-api autofac dependency-resolver

当 Autofac 试图通过依赖解析器解析构造函数参数时,有没有办法一次列出所有丢失的注册?或者是一次通过一个的唯一方法..

以此为例:

public MyWebApiController(IMyInterface myInterface)

我知道实现 IMyInterface 的类 MyInterfaceImpl 必须像这样用 Autofacs ContainerBuilder 注册:

builder.RegisterType<MyInterfaceImpl>().As<IMyInterface>()

但是,如果 MyInterfaceImpl 依赖于其他 10 个构造函数,并且每个构造函数都依赖于一大堆呢?有没有办法让 Autofac 遍历所有尚未注册到 ContainerBuilder 的依赖项,而不是在第一次出现?

采取:

public MyInterfaceImpl(IMyInterface2 myInterface2, IMyInterface3 myInterface3, ... etc ...)

而且每个都有自己的构造函数需要注册..

public MyInterface2Impl(IMyInterfaceB myInterfaceB)

等等

因为我缺少 Autofac 注册,会显示以下异常消息,告诉我必须注册,即 MyInterface2Impl 接口(interface)。

None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'MyWebApiController' can be invoked with the available services and parameters

以及显示它拒绝哪个参数​​的详细信息:

Cannot resolve parameter 'IMyInterface2 myInterface2' of constructor 'Void .ctor(IMyInterface2 myInterface2, IMyInterface3 myInterface3, ... etc ...)

但是我可能有接下来的 5 个丢失的注册。这很烦人,因为我必须启动站点/服务并调用 api Controller ,在我修复每个丢失的注册之后,有时在设置 coctail 时可能会有很多丢失的注册。

那么,Autofac 能否一次显示所有缺失的注册信息?

最佳答案

没有简单的方法可以做您想做的事。我检查了代码,只显示了第一个参数,参见 ConstructorParameterBinding.cs in github repository

for (int i = 0; i < parameters.Length; ++i)
{
    var pi = parameters[i];
    bool foundValue = false;
    foreach (var param in availableParameters)
    {
        Func<object> valueRetriever;
        if (param.CanSupplyValue(pi, context, out valueRetriever))
        {
            _valueRetrievers[i] = valueRetriever;
            foundValue = true;
            break;
        }
    }
    if (!foundValue)
    {
        CanInstantiate = false;
        _firstNonBindableParameter = pi;
        break;
    }

我认为这是出于性能原因。

顺便说一句,您可以使用 ResolveOperationBeginning 事件来获取您想要的特定情况。

#if DEBUG
container.ResolveOperationBeginning += (sender, e) =>
{
    IComponentRegistration registration = null;
    e.ResolveOperation.InstanceLookupBeginning += (sender2, e2) =>
    {
        registration = e2.InstanceLookup.ComponentRegistration;
    };

    e.ResolveOperation.CurrentOperationEnding += (sender2, e2) =>
    {
        if (e2.Exception != null)
        {
            ConstructorInfo ci = registration.Activator.LimitType
                                                       .GetConstructors()
                                                       .First();

            StringBuilder sb = new StringBuilder();
            sb.AppendLine($"Can't instanciate {registration.Activator.LimitType}");

            foreach (ParameterInfo pi in ci.GetParameters())
            {
                if (!((ILifetimeScope)sender).IsRegistered(pi.ParameterType))
                {
                    sb.AppendLine($"\t{pi.ParameterType} {pi.Name} is not registered");
                }
            }

            throw new DependencyResolutionException(sb.ToString(), e2.Exception);
        }
    };
};
#endif

它不会在所有情况下都有效,但如果你只使用构造函数注入(inject)而不使用复杂绑定(bind),它应该足够了。

完整示例在这里:https://dotnetfiddle.net/om16sI

关于c# - 列出依赖解析器 DefaultConstructorFinder 的所有缺失的 Autofac 注册,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34609171/

相关文章:

c# - 使用 WPF/C# 获取有关处理器的信息

javascript - AngularJS $http.post 不适用于 Chrome,仅适用于 IE

c# - Autofac 注册并解析名称

c# - 垂直对齐以使命令栏内容内的文本框居中

c# - 无法将下载的代码覆盖工具转换为 XML

angularjs - webapi owin 使用 token 和 cookie

c# - Web API .net core 2请求检查请求的 header 不为空

c# - JsonConverter 属性 : deserialize using custom constructor and Autofac

c# - 在每个 session 中向 Autofac 中的接口(interface)注册不同的类?

c# - 用于在嵌套范围内查找的最佳数据结构