• 7.1ASP.NET Core中的依赖注入


    7.1ASP.NET Core中的依赖注入

    ASP.Net中Program.cs文件中,第一行var builder = WebApplication.CreateBuilder(args)返回的类型为WebApplicationBuilder类型,在该类型中Services属性为IServiceCollection类型,也就是容器接口,一般把服务都注册到这个Service属性里面

    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddControllers();//将项目中的控制器及相关的服务注册到容器中
    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerGen();//将Swagger相关服务注册到容器中
    //当我们想注册服务的时候,主要把注册代码放到builder.Build()之前就可以
    //注册代码的顺序不会影响程序运行的效果
    var app = builder.Build();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    因为控制器被AddControllers()方法注册到了容器中,所以控制器中可以使用依赖注入的方式,在构造函数中依赖注入其他的类

    public class MyService1
    {
    	public IEnumerable<string> GetNames()
    	{
    		return new string[] { "Tom", "Zack", "Jack" };
    	}
    }
    //如果在var app = builder.Build();之前使用builder.Services.AddScoped();就可以像下面这样来注入服务了
    public class TestController : ControllerBase
    {
    	private readonly MyService1 myService1;
    	public TestController(MyService1 myService1)//构造函数,注入MyService1
    	{
    		this.myService1 = myService1;
    	}
        [HttpGet]
        public string Test()
        {
            var names = myService1.GetNames();
            return string.Join(",", names);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    低频率服务的另类注入方式

    如果一个类中有多个操作方法,这些操作方法用到的服务都要使用构造函数来注入(所有的服务都得包含进来,不管用不用)。如果一个操作方法用到的服务特别耗费资源并且使用频率低,则可以在操作方法中通过参数注入的方式,实现在执行某个方法的时候才注入特定的服务。

    public string Test([FromServices]MyService1 myService1, string name) //只有在调用Test的时候,才注入MyService1,且不需要在构造函数中有
    {
    	var names = myService1.GetNames();
    	return string.Join(",", names) + ",hello:" + name;
    }
    //建议多数还是要才去构造函数的方式来注入
    //[FromServices]只有控制器类的操作方法才能这样用
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    案例

    一个解决方案中会包含多个项目,并且解决方案中会引用各个项目,每个项目都会用到很多被注入的服务,所以我们需要在解决方案中把设计到的服务都要注册进去,这样就会很麻烦。现在开发一个案例来简化这些操作。

    //创建接口和类
    public interface ImoduleInitializer
    {
        public void Initialize(IServiceCollection services);
    }
    
    public static IServiceCollection RunModuleInitializers(this IServiceCollection services,IEnumerable<Assembly> assemblies)
    {
        //扫描所有程序集中实现了IModuleInitializer的类
        foreach (var implType in assemblies.SelectMany(asm =>  asm.GetTypes()).Where(t=>!t.IsAbstract && typeof(IModuleInitializer).IsAssignableFrom(t))
        {
            //创建了ImoduleInitializer类
            var initializer = (IModuleInitializer?)Activator.CreateInstance(implType);
            initializer.Initialize(services);
        }
        return services;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    1. 首先创建一个类库项目,并创建接口IMyService
    public interface IMyService
    {
        void SayHello();
    }
    
    • 1
    • 2
    • 3
    • 4
    1. 创建类库项目demo1,引用IMyService接口
    public class CnService : IMyService
    {
        public void SayHello()
        {
            Console.WriteLine("你好");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1. 在demo1项目中创建IModuleInitializer的实现类ModuleInitializer
    class ModuleInitializer : IModuleInitializer
    {
        public void Initialize(IServiceCollection services)
        {
            services.AddScoped<IMyService, CnService>();//将CnService注册为IMyService的实现服务
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1. 创建控制台程序,添加对上面项目的引用
    ServiceCollection services = new ServiceCollection();
    var assemblies = ReflectionHelper.GetAllReferencedAssemblies();//获取用户的所有程序集,代码过长,没有在这里给出
    services.RunModuleInitializers(assemblies);//扫描指定程序集中所有实现了IModuleInitializer的类,并调用Initialize方法
    using var sp = services.BuildServiceProvider();
    var items = sp.GetServices<IMyService>();
    foreach(var item in items)
    {
        item.SayHello();
    }
    //并没有注册CnService服务但是可以使用
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 相关阅读:
    LeetCode--3.无重复字符的最长子串
    架构案例2017(五十二)
    【牛客编程题】GO语言入门46题
    软考架构设计师知识点
    max96712+max96717驱动调试
    spring高级源码50讲-43-50(spring续)
    构建你的Conda包:使用conda skeleton命令打造包的骨架
    【案例分享】H3C设备配置端口镜像
    经典的arena内存池实现-levelDB的内存池实现
    利用正则表达式限制网页表单里的文本框输入内容
  • 原文地址:https://blog.csdn.net/weixin_44064908/article/details/126445404