首页 文章

Autofac无法在运行时解析某些程序集中的类型,可以在调试器中运行

提问于
浏览
2

在我的解决方案中,我有更多的组件其中一些包括Autofac模块,其中包含来自组件的注册 . 我在启动后立即将所有注册连接在一起 . 到目前为止一切正常,我通过构造函数注入创建了依赖项,Autofac帮助我解决了依赖项 .

(在这个项目中,我在Console应用程序中托管SignalR和WebApi功能 . 我也使用OWIN . )

在我添加了WebApi并使用DI创建了我的第一个控制器之后,我遇到了一个问题 . 在 MyController 的构造函数中,我依赖 MyInterface . 当我尝试在我的控制器上调用任何方法时,我得到了普通的

可以使用可用的服务和参数调用在'MyController'类型上找到'Autofac.Core.Activators.Reflection.DefaultConstructorFinder'的构造函数:无法解析构造函数'Void .ctor(MyInterface)'的参数'MyInterface myInt' .

例外 . 我注意到了什么:

  • 如果我将 MyInterface 替换为另一个组件中的另一个,则加载控制器 .

  • MyInterface 可以在我的代码中的另一个地方解析(在另一个程序集中)

我接着进行了一些调试 . 我试图在我的OWIN Startup类中启动时解决一些类 . 我现在看到的是

  • 我无法解析 MyAssembly1MyAssembly2 中的任何类型

  • 我可以解决 MyAssembly3MyAssembly4 中的所有类型

  • container.Resolve<MyInterface> throws exception 来自代码
    如果我在调试期间通过Visual Studio中的Watch窗口解析它,

  • container.Resolve<MyInterface> 会返回 resolved class

  • 我在 container.ComponentRegistry.Registrations 看到 all 注册

你能告诉我,我错了什么?

更新

我试着提供所有必要的信息,请告诉我,如果我还是忘记了什么 .

这是AssemblyA中的Autofac模块定义

public class AutofacModuleConfig : Module, IAutofacModuleConfig
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<MyWorkingImplementation>().As<IMyWorkingInterface>();

        base.Load(builder);
    }

这是AssemblyB中的Autofac模块定义

public class AutofacModuleConfig : Module, IAutofacModuleConfig
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<MyNotWorkingImplementation>().As<IMyNotWorkingInterface>();

        base.Load(builder);
    }
}

在设置WebHost的程序集中,有一个控制器注册(与之前的结构相同)

builder.RegisterApiControllers(System.Reflection.Assembly.GetExecutingAssembly());

这是我在应用程序启动时注册的方式

private void RegisterModuleDependencies()
{
    var builder = new ContainerBuilder();
    builder.RegisterType<Core.Logger.Log4NetLogger>().As<ILogger>();

    var moduleConfigs = GetModuleConfigurations();
    foreach (var module in moduleConfigs)
        builder.RegisterModule(module);

    container = builder.Build();
}

private List<Autofac.Module> GetModuleConfigurations()
{
    var type = typeof(IAutofacModuleConfig);
    var types = AppDomain.CurrentDomain.GetAssemblies()
        .SelectMany(s => s.GetTypes())
        .Where(p => type.IsAssignableFrom(p) && p.GetConstructor(Type.EmptyTypes) != null);
    return types.Select(t => (Autofac.Module)Activator.CreateInstance(t)).ToList();
}

这是SignalR和WebApi的启动方法

private void Startup(IAppBuilder app)
{
    IDependencyResolver resolver = new AutofacDependencyResolver(container);
    GlobalHost.DependencyResolver = resolver;

    ...

    ConfigureOAuth(app, resolver.Resolve<IAuthorizationService>());

    app.UseCors(CorsOptions.AllowAll);
    app.MapSignalR(new HubConfiguration
    {
        Resolver = resolver,
        EnableDetailedErrors = true,
        EnableJavaScriptProxies = false
    });

    //Host WebApi
    HttpConfiguration webApiConfiguration = new HttpConfiguration();
    webApiConfiguration.MapHttpAttributeRoutes();
    webApiConfiguration.Routes.MapHttpRoute("DefaultWebApi", "api/{controller}/{id}", new { id = RouteParameter.Optional });
    webApiConfiguration.Services.Add(typeof(System.Web.Http.ExceptionHandling.IExceptionLogger), new WebApiExceptionLogger());
    webApiConfiguration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
    app.UseWebApi(webApiConfiguration);
}

出于测试目的,我包含了常见示例中使用的ValuesController . 使用默认构造函数,它自然很好 . 如果我用 IMyWorkingInterface 添加构造函数,正如其名称所暗示的那样,它完美地运行 . 但是,如果我使用 IMyNotWorkingInterface 而不是工作的构造函数包含构造函数,那么我得到了异常 .

public class ValuesController : ApiController
{
    //private readonly TestNamespaceInAssemblyB.IMyNotWorkingInterface notWorkingInstance;

    //public ValuesController(TestNamespaceInAssemblyB.IMyNotWorkingInterface notWorkingInstance)
    //{
    //  this.notWorkingInstance = notWorkingInstance;
    //}

    private readonly TestNamespaceInAssemblyA.IMyWorkingInterface workingInstance;

    public ValuesController(TestNamespaceInAssemblyA.IMyWorkingInterface workingInstance)
    {
        this.workingInstance = workingInstance;
    }

当我将 IMyNotWorkingInterface 作为依赖项添加到另一个程序集(比如说AssemblyC)时,我想再次指出它然后由Autofac解决它而没有错误 .

在调试器中,我在Watch窗口中看到注册 MyNotWorkingImplementation . 此外,我甚至可以从调试器中解析它,因为您可以在图像上看到它 .

enter image description here

更新2

我为Autofac事件创建了事件处理程序,这里的日志显示了当我尝试注入_484120时会发生什么

2017-01-08 13:32:36.920753 | [0x00002acc] | DEBUG | Core        - WebHost                                   | AGENT  | Chile lifetime scope started
2017-01-08 13:32:36.934754 | [0x00002acc] | DEBUG | Core        - WebHost                                   | AGENT  | Resolve operation started
2017-01-08 13:32:36.936754 | [0x00002acc] | DEBUG | Core        - WebHost                                   | AGENT  | Instance lookup is beginning for Activator = ValuesController (DelegateActivator), Services = [API.Agent.Web.Controllers.ValuesController], Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime, Sharing = None, Ownership = ExternallyOwned
2017-01-08 13:32:36.938754 | [0x00002acc] | DEBUG | Core        - WebHost                                   | AGENT  | Instance lookup is beginning for Activator = ValuesController (ReflectionActivator), Services = [API.Agent.Web.Controllers.ValuesController], Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime, Sharing = None, Ownership = OwnedByLifetimeScope
2017-01-08 13:32:36.939754 | [0x00002acc] | DEBUG | Core        - AutofacModuleConfig                       | AGENT  | Resolve for was requested by Activator = ValuesController (ReflectionActivator), Services = [API.Agent.Web.Controllers.ValuesController], Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime, Sharing = None, Ownership = OwnedByLifetimeScope
2017-01-08 13:32:36.966757 | [0x00002acc] | DEBUG | Core        - WebHost                                   | AGENT  | Resolve operation finished
2017-01-08 13:32:36.967757 | [0x00002acc] | ERROR | Core        - WebHost                                   | AGENT  | 
Autofac.Core.DependencyResolutionException: None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'API.Agent.Web.Controllers.ValuesController' can be invoked with the available services and parameters:
Cannot resolve parameter 'TestNamespaceInAssemblyB.IMyNotWorkingInterface notWorkingInstance' of constructor 'Void .ctor(TestNamespaceInAssemblyB.IMyNotWorkingInterface)'.
   at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)
   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__DisplayClass8.<RegistrationsFor>b__3(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)
   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)
2017-01-08 13:32:38.085869 | [0x000029c4] | DEBUG | Core        - WebHost                                   | AGENT  | Child lifetime scope closed

我知道在哪里可以将一些调试代码粘贴到Autofac中吗? (顺便说一句,我使用的是Autofac 3.5.2)

2 回答

  • 1

    好吧,我可以克服这个问题,但我根本无法分辨为什么它不起作用 .

    所以这是输出的结构:

    .\Modules\AssemblyB.dll
    .\AssemblyA.dll
    .\Autofac.dll
    .\...
    .\Application.exe
    

    我在任何项目中都没有任何关于AssemblyB的参考 . 在启动过程中,我扫描Module文件夹中的模块,然后通过调用 Assembly.LoadFrom("...\Modules\AssemblyB.dll") 加载它们 . 加载所有模块后,我调用问题中描述的 RegisterModuleDependencies() 方法 . 完成此设置后,我得到 DependencyResolutionException .

    Solution:

    如果我只是将AssemblyB.dll从Modules文件夹复制到根文件夹,我修改程序集加载逻辑从根文件夹加载此模块然后我的问题vahises,我也可以使用 ValuesController 与我的 IMyNotWorkingInterface .

    如果有人能告诉我这里发生了什么以及为什么原始解决方案不起作用(甚至告诉我该怎么做才能将模块保存在不同的文件夹中)我会接受这个作为答案 .

  • 0

    确保注册控制器 . 您需要为autofac包含WebApi特定的nuget包,并在启动时从容器构建器调用以下方法:

    RegisterApiControllers(Assembly.GetExecutingAssembly());
    

相关问题