Autofac assembly scanning - .NET Core

跟風遠走 提交于 2020-06-28 09:23:13

问题


I've been trying to get assembly scanning working in my .NET core 2.0 project.

The exception I am getting

Autofac.Core.Registration.ComponentNotRegisteredException
  HResult=0x80131500
  Message=The requested service 'Microsoft.AspNetCore.Hosting.Internal.WebHostOptions' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.
  Source=Autofac
  StackTrace:
   at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable`1 parameters)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.AspNetCore.Hosting.WebHostExtensions.<RunAsync>d__4.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Hosting.WebHostExtensions.Run(IWebHost host)
   at Track4Corp.VehicleDatabase.Server.Program.Main(String[] args) in C:\Users\Admin\source\repos\VehicleDatabase-server\src\Track4Corp.VehicleDatabase.Server\Program.cs:line 10

Program.cs

using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;

namespace Track4Corp.VehicleDatabase.Server
{
  public class Program
  {
    public static void Main(string[] args)
    {
      CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
  }
}

Startup class

public class Startup
  {
    public Autofac.IContainer ApplicationContainer { get; private set; }

    public IConfigurationRoot Configuration { get; private set; }

    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
//TODO: Move out of code before release
      services.AddDbContext<UserDBContext>(options => options.UseSqlServer("Server=DESKTOP-9L9IGFE;Database=DB;Trusted_Connection=True;"));

      //Autofac Assembly Registration
      ApplicationContainer = AutoFacAssemblyRegistration.RegisterAllAssemblies();

      return new AutofacServiceProvider(ApplicationContainer);
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
      if (env.IsDevelopment())
      {
        app.UseDeveloperExceptionPage();
      }

      app.Run(async (context) =>
      {
       await context.Response.WriteAsync("Hello World!");
      });

So my actually builder i moved to another project, where I for now scan on a hardcorded path where I know all my dll files are located. I ran it in debug mode and see all of them being there.

  public class AutoFacAssemblyRegistration
  {
    public static IContainer RegisterAllAssemblies()
    {
      var builder = new ContainerBuilder();
      string executingDirectory = Directory.GetCurrentDirectory();
      // string[] files = Directory.GetFiles(executingDirectory, "*.dll");
      string[] files = Directory.GetFiles(@"PATH_HERE", "*.dll");

      var listOfAssemblies = new List<Assembly>();
      foreach (string item in files)
      {
        listOfAssemblies.Add(item: Assembly.LoadFile(item));
      }
      builder.RegisterAssemblyTypes(listOfAssemblies.ToArray()).AsImplementedInterfaces().InstancePerLifetimeScope();
      //builder.RegisterAssemblyModules(listOfAssemblies.ToArray());

      return builder.Build();
    }
  }

I also tried different sort of solutions to register the assemblies, such as

foreach (Assembly item in listOfAssemblies)
{
  System.Type[] assemblyType = item.GetTypes();
  foreach (System.Type typeItem in assemblyType)
  {
    if (typeItem.IsInterface)
    {
      Autofac.Builder.IRegistrationBuilder<object, Autofac.Builder.ConcreteReflectionActivatorData,
        Autofac.Builder.SingleRegistrationStyle> registration =
        builder.RegisterType(typeItem).AsImplementedInterfaces();

      if (typeItem.GetInterfaces().Any(i => i.IsAssignableFrom(typeof(ISingletonDependency))))
      {
        registration.SingleInstance();
      }
      else
      {
        registration.InstancePerRequest();
      }
    }
  }
}

I am wondering if I am doing something wrong, or perhaps this is not possible in .NET core 2.1 projects?

Would be nice if anyone could hint me in the right direction, how to solve my problem.


回答1:


Had a similar issue and solved it by adding containerBuilder.Populate(serviceCollection) before doing containerBuilder.Build().

Following the sample you provided in your question, it would look something like this -

  public class AutoFacAssemblyRegistration
  {
    public static IContainer RegisterAllAssemblies(IServiceCollection services)
    {
      var builder = new ContainerBuilder();
      builder.Populate(services);
      string executingDirectory = Directory.GetCurrentDirectory();
      // string[] files = Directory.GetFiles(executingDirectory, "*.dll");
      string[] files = Directory.GetFiles(@"PATH_HERE", "*.dll");

      var listOfAssemblies = new List<Assembly>();
      foreach (string item in files)
      {
        listOfAssemblies.Add(item: Assembly.LoadFile(item));
      }
      builder.RegisterAssemblyTypes(listOfAssemblies.ToArray()).AsImplementedInterfaces().InstancePerLifetimeScope();
      //builder.RegisterAssemblyModules(listOfAssemblies.ToArray());

      return builder.Build();
    }
  }


来源:https://stackoverflow.com/questions/52568917/autofac-assembly-scanning-net-core

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!