asp.net core后期的版本支持在依赖注入时,一个接口,多个子类实现,依次注入,当需要使用实例时,可以用IEnumerable<接口>来获取实例,进行使用,这种使用方式如下:
接口和子类的定义:
using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;namespace MultiChildDI.Services{public interface IDemoService{void F1();}public class DemoService01 : IDemoService{public DemoService01(){Console.WriteLine("---------------DemoService01");}public void F1(){Console.WriteLine("---------------DemoService01.F1()");}}public class DemoService02 : IDemoService{public DemoService02(){Console.WriteLine("---------------DemoService02");}public void F1(){Console.WriteLine("---------------DemoService02.F1()");}}public class DemoService03 : IDemoService{public DemoService03(){Console.WriteLine("---------------DemoService03");}public void F1(){Console.WriteLine("---------------DemoService03.F1()");}}}
注入
public void ConfigureServices(IServiceCollection services){services.AddScoped<IDemoService, DemoService01>();services.AddScoped<IDemoService, DemoService02>();services.AddScoped<IDemoService, DemoService03>();}
using Microsoft.AspNetCore.Mvc;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Logging;using MultiChildDI.Services;using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;namespace MultiChildDI.Controllers{[][]public class HomeController : ControllerBase{private readonly ILogger<HomeController> _logger;private readonly IEnumerable<IDemoService> _services;public HomeController(ILogger<HomeController> logger, IEnumerable<IDemoService> services){_services = services;_logger = logger;}[]public string First(){_logger.LogInformation("first");var demo01 = _services.SingleOrDefault(s=>s.GetType().Name=="DemoService01");demo01.F1();return "ok";}[]public string SecondError([FromServices] IServiceProvider provider){var demo01 = provider.GetService<DemoService01>();demo01.F1();return "ok";}[]public string Second([FromServices]IServiceProvider provider){_logger.LogInformation("second");var demo01 = provider.GetServices<IDemoService>().First();demo01.F1();return "ok";}}}
这样使用,当子类比较少时可以,或者当注入的单例模式问题不大,如果子类比较多,并且是非单列模式,就会在每次调用时,把所有的子类都实例化,但一个请求,有可能只调用一个子类里的功能,这样就造成其他子类实例化的大量开销浪费,问题每次调用的这个请求都浪费,特别是要求高性能的应用。运行结果如下。

为了改进这个问题,可以用一个工厂来处理这个问题,只实例化要使用的子类即可。
public void ConfigureServices(IServiceCollection services){services.AddScoped<DemoService01>();services.AddScoped<DemoService02>();services.AddScoped<DemoService03>();services.AddScoped<IDemoServiceFactory, DemoServiceFactory>();}
public interface IDemoServiceFactory{IDemoService Create(string name);}public class DemoServiceFactory : IDemoServiceFactory{private readonly IServiceProvider _provider;public DemoServiceFactory(IServiceProvider provider){_provider = provider;}public IDemoService Create(string name){var type = Assembly.GetAssembly(typeof(DemoServiceFactory)).GetType($"MultiChildDI.Services.DemoService{name}");var instance = _provider.GetService(type);return instance as IDemoService;}}
private readonly ILogger<HomeController> _logger;private readonly IDemoServiceFactory _factory;public HomeController(ILogger<HomeController> logger, IDemoServiceFactory factory){_factory = factory;_logger = logger;}[]public string Get(string name){//根据业务分别实例化不同的子类var demo = _factory.Create(name);demo.F1();return "ok";}
调用三个子实例的结果,每次只实例化要使用的子类,节省开销。

来源:https://mp.weixin.qq.com/s/ht-lQ4FIUBeszxQAMPNgeg

发表评论 取消回复