Autofac AsImplementedInterfaces 无法解析依赖关系
Autofac AsImplementedInterfaces fails to resolve dependencies
这对我来说是一个很大的谜团。有时(还找不到模式)autofac 在尝试解决依赖关系时失败,这是错误消息:
None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'IsThereAnyNews.Mvc.Controllers.HomeController' can be invoked with the available services and parameters:
Cannot resolve parameter 'IsThereAnyNews.DataAccess.IRssChannelsRepository rssRepository' of constructor 'Void .ctor(IsThereAnyNews.Services.IUserAuthentication, IsThereAnyNews.Services.ILoginService, IsThereAnyNews.Services.ISessionProvider, IsThereAnyNews.DataAccess.IRssChannelsRepository)'.
这是我如何连接 autofac
public static void RegisterDependencies()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetCallingAssembly());
builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces();
builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
.Where(t => t.Name.EndsWith("Service"))
.AsImplementedInterfaces();
// other registrations goes here
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
项目设置是这样完成的:
ASP.MVC
-> Interfaces (where needed)
-> Autofac
-> Interface
-> Implementations (*Repository, *Services)
然而,由于某些神秘的(对我来说)原因,我的脸被这个错误打脸了。谁能给我解释一下,我做错了什么
编辑
这是 RssChannelsRepository
的实现
public class RssChannelsRepository : IRssChannelsRepository
{
private readonly ItanDatabaseContext database;
public RssChannelsRepository(ItanDatabaseContext database)
{
this.database = database;
}
}
ItanDatabaseContext 是这样注册的:
builder.RegisterType<ItanDatabaseContext>().InstancePerLifetimeScope();
无法确定是否加载了内容,目前我在 Azure 上遇到了这个问题。对我来说,当我进行一些调试会话时会发生这种情况,在这里和那里更改一段代码并进行增量构建。然后出现此问题,但并非总是如此。为了解决它,我简单地 运行 完全重建,仅此而已。
问题可能是由 AppDomain.CurrentDomain.GetAssemblies()
调用引起的。根据MSDN方法:
Gets the assemblies that have been loaded into the execution context of this application domain.
如果程序集尚未加载,则不会从列表中return编辑它。由于您的 bootstrap 代码在应用程序启动期间运行得非常早,因此可能没有静态依赖于包含您的存储库的程序集中的类型的任何方法。如果是这种情况,该程序集将不会加载,也不会从 GetAssemblies()
方法中 returned,导致 Autofac 中没有注册。
为确保以确定的方式加载所有程序集,您应该调用 BuildManager.GetReferencedAssemblies()。例如:
public static void RegisterDependencies()
{
BuildManager.GetReferencedAssemblies();
var builder = new ContainerBuilder();
builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces();
// ...
}
使用来自 GetReferencedAssemblies
的程序集 return 作为 Autofac 的输入会更有效,因为 AppDomain.GetAssemblies()
会 return 所有 System.*
程序集作为好吧,这将导致 Autofac 也通过它们。例如:
public static void RegisterDependencies()
{
var assemblies = BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToArray();
var builder = new ContainerBuilder();
builder.RegisterAssemblyTypes(assemblies)
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces();
// ...
}
这都是 Autofac 文档中的 described in more detail。
这对我来说是一个很大的谜团。有时(还找不到模式)autofac 在尝试解决依赖关系时失败,这是错误消息:
None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'IsThereAnyNews.Mvc.Controllers.HomeController' can be invoked with the available services and parameters: Cannot resolve parameter 'IsThereAnyNews.DataAccess.IRssChannelsRepository rssRepository' of constructor 'Void .ctor(IsThereAnyNews.Services.IUserAuthentication, IsThereAnyNews.Services.ILoginService, IsThereAnyNews.Services.ISessionProvider, IsThereAnyNews.DataAccess.IRssChannelsRepository)'.
这是我如何连接 autofac
public static void RegisterDependencies()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetCallingAssembly());
builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces();
builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
.Where(t => t.Name.EndsWith("Service"))
.AsImplementedInterfaces();
// other registrations goes here
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
项目设置是这样完成的:
ASP.MVC
-> Interfaces (where needed)
-> Autofac
-> Interface
-> Implementations (*Repository, *Services)
然而,由于某些神秘的(对我来说)原因,我的脸被这个错误打脸了。谁能给我解释一下,我做错了什么
编辑 这是 RssChannelsRepository
的实现public class RssChannelsRepository : IRssChannelsRepository
{
private readonly ItanDatabaseContext database;
public RssChannelsRepository(ItanDatabaseContext database)
{
this.database = database;
}
}
ItanDatabaseContext 是这样注册的:
builder.RegisterType<ItanDatabaseContext>().InstancePerLifetimeScope();
无法确定是否加载了内容,目前我在 Azure 上遇到了这个问题。对我来说,当我进行一些调试会话时会发生这种情况,在这里和那里更改一段代码并进行增量构建。然后出现此问题,但并非总是如此。为了解决它,我简单地 运行 完全重建,仅此而已。
问题可能是由 AppDomain.CurrentDomain.GetAssemblies()
调用引起的。根据MSDN方法:
Gets the assemblies that have been loaded into the execution context of this application domain.
如果程序集尚未加载,则不会从列表中return编辑它。由于您的 bootstrap 代码在应用程序启动期间运行得非常早,因此可能没有静态依赖于包含您的存储库的程序集中的类型的任何方法。如果是这种情况,该程序集将不会加载,也不会从 GetAssemblies()
方法中 returned,导致 Autofac 中没有注册。
为确保以确定的方式加载所有程序集,您应该调用 BuildManager.GetReferencedAssemblies()。例如:
public static void RegisterDependencies()
{
BuildManager.GetReferencedAssemblies();
var builder = new ContainerBuilder();
builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces();
// ...
}
使用来自 GetReferencedAssemblies
的程序集 return 作为 Autofac 的输入会更有效,因为 AppDomain.GetAssemblies()
会 return 所有 System.*
程序集作为好吧,这将导致 Autofac 也通过它们。例如:
public static void RegisterDependencies()
{
var assemblies = BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToArray();
var builder = new ContainerBuilder();
builder.RegisterAssemblyTypes(assemblies)
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces();
// ...
}
这都是 Autofac 文档中的 described in more detail。