使用web api的Autofac无法解析依赖关系

时间:2017-03-09 18:50:49

标签: asp.net-web-api owin autofac

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

我的控制器需要IClass1的依赖关系。它似乎已注册,但由于某种原因,它无法在运行时解决。知道问题可能是什么吗?

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

Registrations

并且生命周期范围是正确的,它被设置为:AutofacWebRequest

enter image description here

代码

注册记忆

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”类型的控制器时发生错误。确保控制器具有无参数的公共构造函数。

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,它仍然会失败,这让我相信我正在使用的堆栈组合存在某种错误。

1 个答案:

答案 0 :(得分:0)

实际上这与Autofac无关。我使用的是Assembly.LoadFile,它没有考虑到程序集绑定。