【发布时间】:2017-01-06 12:06:26
【问题描述】:
在我的解决方案中,我有更多的程序集。其中一些包括一个带有来自程序集的注册的 Autofac 模块。我在启动后立即将所有注册连接在一起。到目前为止一切正常,我通过构造函数注入创建了依赖项,Autofac 帮助我解决了依赖项。
(在这个项目中,我在控制台应用程序中托管 SignalR 和 WebApi 功能。我也使用 OWIN。)
在我添加了 WebApi 并使用 DI 创建了我的第一个控制器后,我遇到了一个问题。在MyController 的构造函数中,我依赖于MyInterface。当我尝试调用控制器上的任何方法时,我得到了普通的
在“MyController”类型上使用“Autofac.Core.Activators.Reflection.DefaultConstructorFinder”找到的任何构造函数都不能被可用的服务和参数调用: 无法解析构造函数“Void .ctor(MyInterface)”的参数“MyInterface myInt”。
异常。我注意到了什么:
- 如果我将
MyInterface替换为来自另一个程序集的另一个,则会加载控制器。 -
MyInterface可以在我的代码中的另一个位置(在另一个程序集中)解决
我继续进行一些调试。我试图在我的 OWIN Startup 课程中在启动时解决一些课程。我现在看到的是
- 我无法解析来自
MyAssembly1、MyAssembly2的任何类型 - 我可以解析来自
MyAssembly3、MyAssembly4的所有类型 -
container.Resolve<MyInterface>从代码中抛出异常 -
container.Resolve<MyInterface>如果我在调试期间通过 Visual Studio 中的 Watch 窗口解决它,则返回 已解决的类 - 我在
container.ComponentRegistry.Registrations看到所有注册
你能告诉我,我做错了什么吗?
更新
我尽量提供所有必要的信息,如果我仍然忘记了什么,请告诉我。
这是 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。更重要的是,我什至可以从调试器中解决它,正如您在图像上看到的那样。
更新 2
我为 Autofac 事件创建了事件处理程序,这里的日志显示了当我尝试注入 IMyNotWorkingInterface 时会发生什么
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)
【问题讨论】:
-
信息不足。您需要发布代码,显示您如何枚举程序集以及在何处注册内容。您所看到的长短:Autofac 没有注册
MyInterface。 -
我看不出这与您的问题有什么关系,或者即使您可能忘记将其包含在代码中,但是当您使用 Autofac、OWIN 和 Web API 时,您应该调用 @ 987654348@ 和
app.UseAutofacWebApi(HttpConfiguration)在调用app.UseWebApi之前,如the documentation 所示。你能试试以防万一吗? -
@MickaëlDerriey 感谢您的提示,但不幸的是它没有帮助。问题是一样的
标签: c# dependency-injection signalr asp.net-web-api2 autofac