7.1ASP.NET Core中的依赖注入
ASP.Net中Program.cs文件中,第一行var builder = WebApplication.CreateBuilder(args)
返回的类型为WebApplicationBuilder
类型,在该类型中Services属性为IServiceCollection
类型,也就是容器接口,一般把服务都注册到这个Service属性里面
1 2 3 4 5 6 7
| var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen();
var app = builder.Build();
|
因为控制器被AddControllers()方法注册到了容器中,所以控制器中可以使用依赖注入的方式,在构造函数中依赖注入其他的类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class MyService1 { public IEnumerable<string> GetNames() { return new string[] { "Tom", "Zack", "Jack" }; } }
public class TestController : ControllerBase { private readonly MyService1 myService1; public TestController(MyService1 myService1) { this.myService1 = myService1; } [HttpGet] public string Test() { var names = myService1.GetNames(); return string.Join(",", names); } }
|
低频率服务的另类注入方式
如果一个类中有多个操作方法,这些操作方法用到的服务都要使用构造函数来注入(所有的服务都得包含进来,不管用不用)。如果一个操作方法用到的服务特别耗费资源并且使用频率低,则可以在操作方法中通过参数注入的方式,实现在执行某个方法的时候才注入特定的服务。
1 2 3 4 5 6 7
| public string Test([FromServices]MyService1 myService1, string name) { var names = myService1.GetNames(); return string.Join(",", names) + ",hello:" + name; }
|
案例
一个解决方案中会包含多个项目,并且解决方案中会引用各个项目,每个项目都会用到很多被注入的服务,所以我们需要在解决方案中把设计到的服务都要注册进去,这样就会很麻烦。现在开发一个案例来简化这些操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public interface ImoduleInitializer { public void Initialize(IServiceCollection services); }
public static IServiceCollection RunModuleInitializers(this IServiceCollection services,IEnumerable<Assembly> assemblies) { foreach (var implType in assemblies.SelectMany(asm => asm.GetTypes()).Where(t=>!t.IsAbstract && typeof(IModuleInitializer).IsAssignableFrom(t)) { var initializer = (IModuleInitializer?)Activator.CreateInstance(implType); initializer.Initialize(services); } return services; }
|
- 首先创建一个类库项目,并创建接口IMyService
1 2 3 4
| public interface IMyService { void SayHello(); }
|
- 创建类库项目demo1,引用IMyService接口
1 2 3 4 5 6 7
| public class CnService : IMyService { public void SayHello() { Console.WriteLine("你好"); } }
|
- 在demo1项目中创建IModuleInitializer的实现类ModuleInitializer
1 2 3 4 5 6 7
| class ModuleInitializer : IModuleInitializer { public void Initialize(IServiceCollection services) { services.AddScoped<IMyService, CnService>(); } }
|
- 创建控制台程序,添加对上面项目的引用
1 2 3 4 5 6 7 8 9 10
| ServiceCollection services = new ServiceCollection(); var assemblies = ReflectionHelper.GetAllReferencedAssemblies(); services.RunModuleInitializers(assemblies); using var sp = services.BuildServiceProvider(); var items = sp.GetServices<IMyService>(); foreach(var item in items) { item.SayHello(); }
|