带有 web api 的 Autofac 未解析依赖项

Autofac with web api not resolving dependencies

我很难理解为什么我似乎无法让 autofac 3.5.2(也尝试使用 4.4 版)与 Web Api 2.2 + Owin 一起工作。

我有一个需要依赖 IClass1 的控制器。它似乎已注册,但由于某种原因无法在运行时解析。知道问题出在哪里吗?

有问题的注册似乎在那里(见第 4 行 - Class1 注册为 IClass1):

并且lifetime scope是对的,设置为:AutofacWebRequest

代码

注册

public void Configuration(IAppBuilder app)
{
    var suffix = typeof(DefaultHttpControllerSelector).GetField("ControllerSuffix", BindingFlags.Static | BindingFlags.Public);

    if (suffix != null) suffix.SetValue(null, string.Empty);

    var container = InitializeDiContainer(app);
    var config = new HttpConfiguration
    {
        DependencyResolver = new AutofacWebApiDependencyResolver(container)
    };

    config.MapHttpAttributeRoutes();

    app.UseAutofacMiddleware(container);
    app.UseAutofacWebApi(config);
    app.UseWebApi(config);

    Mapper.Initialize(cfg =>
    {
        foreach (var profile in container.Resolve<IEnumerable<Profile>>())
        {
            cfg.AddProfile(profile);
        }
    });

    OnEndpointConfigurationCompleted(app, container);
}

private IContainer InitializeDiContainer(IAppBuilder app)
{
    var builder = new ContainerBuilder();
    var allAssemblies = AssemblyUtils.GetAllAssemblies();

    builder.RegisterApiControllers("Endpoint", AssemblyUtils.GetEndpointAssemblies());

    builder.RegisterAssemblyTypes(AssemblyUtils.GetAllAssemblies())
        .Where(t => typeof(IReadModelService).IsAssignableFrom(t) ||
            typeof(IRepository).IsAssignableFrom(t))
        .AsImplementedInterfaces()
        .InstancePerRequest()
        .PropertiesAutowired();

    builder.RegisterAssemblyTypes(AssemblyUtils.GetAllAssemblies())
        .Where(t => typeof(IProvider).IsAssignableFrom(t))
        .AsImplementedInterfaces()
        .InstancePerRequest()
        .PropertiesAutowired();

    var configFilePath = Path.Combine(HttpRuntime.BinDirectory, "endpointConfig.json");

    builder.Register(ctx => JsonConvert.DeserializeObject<Class1Setting>(File.ReadAllText(configFilePath)))
        .InstancePerRequest();

    return builder.Build();
}

依赖关系

public class Class1 : IClass1
{ }

public interface IClass1 : IReadModelService
{ }

public class Class1Setting
{
    public string DataSource { get; set; }
}

控制器

控制器无法解析 IClass1 实例。

public class DeviceQueriesEndpoint : ApiController, IDeviceQueriesEndpoint
{
    private IClass1 _class1;


    public DeviceQueriesEndpoint(IClass1 class1)
    {
        _class1 = class1;
    }
}

异常

这是我在运行时得到的异常:

尝试创建 'DeviceQueriesEndpoint' 类型的控制器时出错。确保控制器具有无参数 public 构造函数。

Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>
An error occurred when trying to create a controller of type 'DeviceQueriesEndpoint'. Make sure that the controller has a parameterless public constructor.
</ExceptionMessage>
<ExceptionType>System.InvalidOperationException</ExceptionType>
<StackTrace>
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request) at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()
</StackTrace>
<InnerException>
<Message>An error has occurred.</Message>
<ExceptionMessage>
An error occurred during the activation of a particular registration. See the inner exception for details. Registration: Activator = DeviceQueriesEndpoint (DelegateActivator), Services = [xpto.Middleware.Api.Device.Endpoint.DeviceQueriesEndpoint], Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime, Sharing = None, Ownership = ExternallyOwned ---> An error occurred during the activation of a particular registration. See the inner exception for details. Registration: Activator = DeviceQueriesEndpoint (ReflectionActivator), Services = [xpto.Middleware.Api.Device.Endpoint.DeviceQueriesEndpoint], Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime, Sharing = None, Ownership = OwnedByLifetimeScope ---> None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'xpto.Middleware.Api.Device.Endpoint.DeviceQueriesEndpoint' can be invoked with the available services and parameters: Cannot resolve parameter 'xpto.ClassLibrary1.IClass1 class1' of constructor 'Void .ctor(xpto.ClassLibrary1.IClass1)'. (See inner exception for details.) (See inner exception for details.)
</ExceptionMessage>
<ExceptionType>Autofac.Core.DependencyResolutionException</ExceptionType>
<StackTrace>
at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters) at Autofac.Core.Resolving.InstanceLookup.Execute() at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters) at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters) at Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters) at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance) at Autofac.ResolutionExtensions.ResolveOptionalService(IComponentContext context, Service service, IEnumerable`1 parameters) at Autofac.ResolutionExtensions.ResolveOptional(IComponentContext context, Type serviceType) at Autofac.Integration.WebApi.AutofacWebApiDependencyScope.GetService(Type serviceType) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
</StackTrace>
<InnerException>
<Message>An error has occurred.</Message>
<ExceptionMessage>
An error occurred during the activation of a particular registration. See the inner exception for details. Registration: Activator = DeviceQueriesEndpoint (ReflectionActivator), Services = [xpto.Middleware.Api.Device.Endpoint.DeviceQueriesEndpoint], Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime, Sharing = None, Ownership = OwnedByLifetimeScope ---> None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'xpto.Middleware.Api.Device.Endpoint.DeviceQueriesEndpoint' can be invoked with the available services and parameters: Cannot resolve parameter 'xpto.ClassLibrary1.IClass1 class1' of constructor 'Void .ctor(xpto.ClassLibrary1.IClass1)'. (See inner exception for details.)
</ExceptionMessage>
<ExceptionType>Autofac.Core.DependencyResolutionException</ExceptionType>
<StackTrace>
at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters) at Autofac.Core.Resolving.InstanceLookup.Execute() at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters) at Autofac.Core.Resolving.InstanceLookup.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters) at Autofac.Core.Registration.ExternalRegistrySource.<>c__DisplayClass2_0.<RegistrationsFor>b__2(IComponentContext c, IEnumerable`1 p) at Autofac.Core.Activators.Delegate.DelegateActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters) at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)
</StackTrace>
<InnerException>
<Message>An error has occurred.</Message>
<ExceptionMessage>
None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'xpto.Middleware.Api.Device.Endpoint.DeviceQueriesEndpoint' can be invoked with the available services and parameters: Cannot resolve parameter 'xpto.ClassLibrary1.IClass1 class1' of constructor 'Void .ctor(xpto.ClassLibrary1.IClass1)'.
</ExceptionMessage>
<ExceptionType>Autofac.Core.DependencyResolutionException</ExceptionType>
<StackTrace>
at Autofac.Core.Activators.Reflection.ReflectionActivator.GetValidConstructorBindings(IComponentContext context, IEnumerable`1 parameters) at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters) at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)
</StackTrace>
</InnerException>
</InnerException>
</InnerException>
</Error>

我尝试过的事情

如果我手动注册它起作用的具体类型,它是奇数:

builder.RegisterType<Class1>().As<IClass1>();

如果我删除构造函数并手动尝试在动作中解析 IClass1,它仍然会失败,这让我相信我正在使用的堆栈组合存在某种错误。

其实这与Autofac无关。我使用的 Assembly.LoadFile 没有考虑程序集绑定。