我们有一个dnx46 Web项目,它在启动期间使用autofac程序集扫描来注册类型。我们的project.json依赖项包括:
"Autofac.Configuration": "4.0.0-rc1-268",
"Autofac.Extensions.DependencyInjection": "4.0.0-rc1-177",
"Autofac.Extras.CommonServiceLocator": "3.2.0",
"Microsoft.AspNet.Hosting": "1.0.0-rc1-final",
"Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final",
"Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
"Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-rc1-final",
"Microsoft.AspNet.Mvc.ViewFeatures": "6.0.0-rc1-final",
"Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
"Microsoft.AspNet.Session": "1.0.0-rc1-final",
"Microsoft.AspNet.StaticFiles": "1.0.0-rc1-final",
"Microsoft.AspNet.Tooling.Razor": "1.0.0-rc1-final",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0-rc1-final",
"Microsoft.Extensions.Configuration.Json": "1.0.0-rc1-final",
"Microsoft.Extensions.Logging": "1.0.0-rc1-final",
"Microsoft.Extensions.Logging.Console": "1.0.0-rc1-final",
"Microsoft.Extensions.Logging.Debug": "1.0.0-rc1-final",
"Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0-rc1-final",
"Newtonsoft.Json": "8.0.3"
我们的startup.cs ConfigureServices方法如下所示:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddSingleton(serviceType => Configuration);
services.AddInstance<Microsoft.Extensions.Configuration.IConfiguration>(Configuration);
services.AddCaching();
services.AddSession();
services.AddMvc();
var builder = new ContainerBuilder();
var assemblies = Directory.GetFiles(<ourBinDirectoryPath>, "*.dll", SearchOption.TopDirectoryOnly).Select(Assembly.LoadFrom);
foreach (var assembly in assemblies)
{
builder.RegisterAssemblyTypes(assembly).Where(t => t.Name.EndsWith("Service") || t.Name.EndsWith("Repository") || t.Name.EndsWith("DataContext")).AsSelf().AsImplementedInterfaces();
builder.RegisterAssemblyTypes(assembly).Where(t => !t.Name.EndsWith("Service") && !t.Name.EndsWith("Repository") && !t.Name.EndsWith("DataContext")).AsSelf().AsImplementedInterfaces().InstancePerDependency();
}
builder.Populate(services);
var container = builder.Build();
return container.Resolve<IServiceProvider>();
}
我们的流程是,我们构建了多个项目,将此项目需要的dll删除到自定义bin文件夹中。在启动时,我们扫描这些程序集以使用Autofac注册类型。我们在一个概念验证项目中做到了这一点,它没有问题。在我们的新项目中,我们有以下问题:
在尝试了很多事情之后,我接受了我们的概念证明项目并将其复制到我们的新解决方案中(如果我们在设置新项目时错过了一些小设置或某些事情),并且不良行为仍在继续。我开始认为我们的程序集引入了一些错误(因为这些是复制后唯一已经改变的东西),但Autofac在扫描期间不会抛出错误,而只是不使用它正确扫描的类型
修改1
我创建并发布了一个very simplified example来重现我遇到的问题。您应该能够将其拉下并运行它以重现错误。您应该在home控制器构造函数中收到错误,指示服务解析失败。
注意:运行此示例时,它会执行.bat文件,该文件将域项目中的输出dll放入用户配置文件.nuget文件夹中。
修改2
根据@Travis Illig的建议将界面拆分为抽象文件夹。一旦我这样做,解决方案开始工作。我们把它分成了我们的“真实”项目,但它没有用。仍在尝试找出原因。
编辑3
所以终于让我们的项目再次运作。问题最终成了几件事:
这让我花费了更长的时间来弄清楚,而我现在最大的问题是Autofac会无声地失败。我真的希望它会爆炸,并给我一些调试输出或表明存在问题的东西。相反,一切似乎都扫描并加载正常,但是当你去使用容器时,什么都不会解决。
答案 0 :(得分:2)
有可能是按照这样的顺序加载程序集,由于未加载先决条件程序集,因此无法加载某些类型。
例如,假设您有包含接口IComponent
的程序集A.还要说你有程序集B,它包含一个实现Component
的类IComponent
。如果首先加载程序集B,则类型Component
将不可加载,因为它实现的接口未定义。
进行类型扫描时,Autofac会尝试尽可能安全,如果输出无法加载的类型,则不会爆炸。您可以在scanning registration source中看到它使用特殊的安全方法进行加载。
在你的加标代码中,我认为加载的程序集要少得多,所以你最终以正确的顺序加载东西。快乐的意外。当你进入更大的项目时,更容易控制负载顺序并导致这样的问题。