通过Nuget安装两个包 => Autofac Autofac.Extensions.DependencyInjection
public static class Demo { public interface IAccount { } public interface IMessage { } public interface ITool { } public class Base : IDisposable { public Base() { Console.WriteLine($"{GetType().Name} Created"); } public void Dispose() { Console.WriteLine($"{GetType().Name} Disposed"); } } public class Account : Base, IAccount { } public class Message : Base, IMessage { } public class Tool : Base, ITool { } public static void Run() { //.NET Core 服务集合 var serviceCollection = new ServiceCollection() .AddTransient<IAccount, Account>() .AddTransient<IMessage, Message>(); var containerBuilder = new ContainerBuilder(); //将服务集合添加到Autofac containerBuilder.Populate(serviceCollection); //通过类型注册将服务添加到Autofac containerBuilder.RegisterType().As(); var container = containerBuilder.Build(); IServiceProvider provider = new AutofacServiceProvider(container); Debug.Assert(provider.GetService() is Account); } }
那么使用Autofac有哪些其它优势?下面看看 属性注入和程序集注入
public static class Demo { public interface IAccount { } public interface IMessage { } public interface ITool { } public interface ITest { public IMessage Message { get; set; } } public class Base { public Base() { Console.WriteLine($"{GetType().Name} Created"); } } public class Account : Base, IAccount { } public class Message : Base, IMessage { } public class Tool : Base, ITool { } public class Test : Base, ITest { public IMessage Message { get; set; } public Test(IAccount account, ITool tool) { Console.WriteLine($"Ctor : Test(IAccount, ITool)"); } } public static void Run() { //.NET Core 服务集合 //var serviceCollection = new ServiceCollection() // .AddTransient<ITool, Tool>(); var containerBuilder = new ContainerBuilder(); //将服务集合添加到Autofac //containerBuilder.Populate(serviceCollection); //属性注入 containerBuilder.RegisterType<Test>().As<ITest>().PropertiesAutowired(); //程序集注入 containerBuilder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()) .Where(t => t.BaseType == typeof(Base)) .As(t => t.GetInterfaces()[0])//调用As方法,暴露服务 .InstancePerLifetimeScope();//每个生命周期作用域的组件在每个嵌套的生命周期作用域中最多只会有一个单一实例 var container = containerBuilder.Build(); IServiceProvider provider = new AutofacServiceProvider(container); Debug.Assert(provider.GetService<IAccount>() is Account); Debug.Assert(provider.GetService<IMessage>() is Message); Debug.Assert(provider.GetService<ITool>() is Tool); var test = provider.GetService<ITest>(); Debug.Assert(test.Message is Message); }
(2)ASP.NET Core 内置DI 与 Autofac 比较
public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); services.AddTransient<IAccount, Account>(); }
内置DI 在Startup类 ConfigureServices通过AddTransient方式注册
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }) .UseServiceProviderFactory(new AutofacServiceProviderFactory());
Startup.cs // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); //services.AddTransient<IAccount, Account>();//内置DI } public void ConfigContainer(ContainerBuilder containerBuilder) { //containerBuilder.RegisterType<Account>().As<IAccount>(); var assembly = Assembly.GetEntryAssembly(); containerBuilder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()) .Where(t => t.BaseType == typeof(Base)) .As(t => t.GetInterfaces()[0]) .InstancePerLifetimeScope(); }
Autofac 需要在Program.cs中替换 .NET Core的默认容器 UseServiceProviderFactory(new AutofacServiceProviderFactory())
在 Startup.cs 中 创建ConfigContainer方法,服务注册和 控制台应用相似;
真正在实际项目中按照以上方式注册服务会很麻烦,难以维护,可读性差;Autofac提供了一种以模块化方式进行注册
比如我们有不同的业务模块 AModule BModule...,将这些module继承 Autofac.Module 重写Load方法进行服务注册
最后在ConfigContainer中RegisterModule进行模块化注册
public class AModule : Autofac.Module { protected override void Load(ContainerBuilder builder) { var containerBaseType = typeof(ControllerBase); builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()) .Where(t => containerBaseType.IsAssignableFrom(t) && t != containerBaseType) .PropertiesAutowired(); } } public void ConfigContainer(ContainerBuilder containerBuilder) { containerBuilder.RegisterModule<AModule>(); }
原文:https://www.cnblogs.com/louiszh/p/14121707.html