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{ [ApiController] [Route("[controller]")] 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; } [HttpGet("/first")] public string First() { _logger.LogInformation("first"); var demo01 = _services.SingleOrDefault(s=>s.GetType().Name=="DemoService01"); demo01.F1(); return "ok"; } [HttpGet("/seconderror")] public string SecondError([FromServices] IServiceProvider provider) { var demo01 = provider.GetService<DemoService01>(); demo01.F1(); return "ok"; } [HttpGet("/second")] 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;}[HttpGet]public string Get(string name){    //根据业务分别实例化不同的子类 var demo = _factory.Create(name);    demo.F1(); return "ok";}

调用三个子实例的结果,每次只实例化要使用的子类,节省开销。

图片

来源:https://mp.weixin.qq.com/s/ht-lQ4FIUBeszxQAMPNgeg
点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信小程序

微信扫一扫体验

立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部