Autofac无法解析asp.net 5中的程序集扫描类型

Jer*_*ong 7 asp.net asp.net-mvc autofac

我们有一个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"
Run Code Online (Sandbox Code Playgroud)

我们的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>();
}
Run Code Online (Sandbox Code Playgroud)

我们的流程是,我们构建了几个项目,将此项目需要的dll删除到自定义bin文件夹中.在启动时,我们扫描这些程序集以使用Autofac注册类型.我们在一个概念验证项目中做到了这一点,它没有问题.在我们的新项目中,我们有以下问题:

  1. 如果您尝试在控制器构造函数中解析服务,则会抛出错误,指示Microsoft依赖注入无法解析该服务.不确定为什么它不在这里使用Autofac提供商.
  2. 如果我们在启动时手动解析单个类型以及组装扫描,我们将在控制器构造中出现错误,指示Autofac无法解析服务(在此处使用Autofac提供程序,但仍未找到我们的类型).
  3. 如果在ConfigurationServices中返回之前检查构建器和容器,它似乎已注册了所有类型.但是,如果我更改控制器以注入IServiceProvider,然后尝试从中解析服务,它会准确地使用Autofac提供程序,但我总是返回null(没有找到服务).

在尝试了很多东西之后,我采用了我们的概念验证项目并将其复制到我们的新解决方案中(如果我们在设置新项目时错过了一些小设置或某些事情),并且不良行为仍在继续.我开始认为我们的程序集引入了一些错误(因为这些是复制后唯一已经改变的东西),但Autofac在扫描期间不会抛出错误,而只是不使用它正确扫描的类型.

编辑1

我创建并发布了一个非常简单的示例,它重现了我遇到的问题.您应该能够将其拉下并运行它以重现错误.您应该在home控制器构造函数中收到错误,指示服务解析失败.

注意:运行此示例时,它会执行.bat文件,该文件将域项目中的输出dll放入用户配置文件.nuget文件夹中.

编辑2

根据@Travis Illig的推荐将界面拆分为抽象文件夹.一旦我这样做,解决方案开始工作.我们把它分成了我们的"真实"项目,但它没有用.仍在试验弄清楚原因.

编辑3

所以终于让我们的项目再次运作.问题最终成了几件事:

  1. 我们的Web项目中列出了一个抽象项目依赖项,我们还从该程序集中加载并扫描了dll(双重加载).(我认为这是一个大问题.)
  2. 我们的NuGet版本很糟糕,所以我认为它们没有正确加载.我们使用1.0.0-1,这是一种无效的预发布格式.将其更新为1.0.0-b1,事情似乎开始变得更好了.

这花了我更长的时间来弄清楚,而我现在最大的问题是Autofac会无声地失败.我真的希望它会爆炸,并给我一些调试输出或表明存在问题的东西.相反,一切似乎都扫描并加载正常,但是当你去使用容器时,没有什么能解决.

Tra*_*lig 2

程序集的加载顺序很可能是由于未加载必备程序集而无法加载某些类型。

例如,假设您有包含接口的程序集IComponentA。还假设您有程序集 B,其中包含Component实现IComponent. 如果您首先加载程序集 B,则该类型Component将无法加载,因为它实现的接口未定义。

在进行类型扫描时,Autofac 会尽可能安全,如果 out 遇到无法加载的类型,也不会爆炸。您可以在扫描注册源中看到它使用特殊的安全方法来进行加载。

在您的尖峰代码中,我敢打赌要加载的程序集要少得多,因此您最终会以正确的顺序加载内容。快乐的意外。当您进入较大的项目时,很容易无法控制加载顺序并导致此类问题。