我的企业网站怎么seo,网站设计方案案例分析,注册网站后如何注销账号,西南交通建设集团有限公司网站文章目录 前言什么是依赖注入C# 使用依赖注入框架介绍 Microsoft.Extensions.DependencyInjectionNuget安装简单单例使用打印结果 自动装配举例自动装配测试用例打印结果自动装配执行顺序测试用例有歧义构造函数渐进式构造函数循环依赖 自动装配结论 手动装配手动注入别名注入 … 文章目录 前言什么是依赖注入C# 使用依赖注入框架介绍 Microsoft.Extensions.DependencyInjectionNuget安装简单单例使用打印结果 自动装配举例自动装配测试用例打印结果自动装配执行顺序测试用例有歧义构造函数渐进式构造函数循环依赖 自动装配结论 手动装配手动注入别名注入 依赖注入的构造顺序 结尾 前言
依赖注入是一个非常重要的编程思想就和面向过程和面向对象一样IOC和控制反转是一种解耦的编程思想。
什么是依赖注入 [C#]理解和入门依赖注入 为什么要用IOC:inversion of controll反转控制把创建对象的权利交给框架 C# 使用依赖注入
框架介绍
目前.NET 有两个最优的依赖注入框架
Microsoft.Extensions.DependencyInjection微软官方依赖注入框架听说在.net core 8.0得到了最强的性能提升Autofac听说也是最强的依赖注入框架性能强开销低功能完善。 Dependency injection in ASP.NET Core Autofac 官网 深入浅出依赖注入容器——Autofac Microsoft.Extensions.DependencyInjection
目前打算用微软的IOC毕竟是官方背书性能有保证。 C# 依赖注入IServiceCollection的AddSingleton方法使用 Nuget安装 简单单例使用
声明个测试类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace NETCore8.Models
{public class Person{public int Id { get; set; }public string ?Name { get; set; }public int Age { get; set; }}
}
主函数代码
using Microsoft.Extensions.DependencyInjection;
using NETCore8.Models;
using Newtonsoft.Json;
using System.ComponentModel.Design;namespace NETCore8
{internal class Program{static void Main(string[] args){//构造依赖注入容器IServiceCollection services new ServiceCollection();//注入Person单例生命周期暂时不展开services.AddSingletonPerson();var builder services.BuildServiceProvider();//初始化单例var res builder.GetServicePerson();res.Name 小刘;res.Age 15;Console.WriteLine(JsonConvert.SerializeObject(res));//从容器中拿到Person单例确认是否已被赋值为小刘var res2 builder.GetServicePerson();Console.WriteLine(JsonConvert.SerializeObject(res2));//修改单例查看容器中的单例是否被修改res2.Name 小红;res2.Age 23;//再从容器中拿出单例var res3 builder.GetServicePerson();Console.WriteLine(JsonConvert.SerializeObject(res3));Console.WriteLine(Hello, World!);Console.ReadKey();}}
}
打印结果 这个说明这个单例一旦被修改了容器中的数据就会被修改。但是这样仅仅是和全局静态的效果一样。依赖注入没有这么简单
自动装配
自动装配的意思就是自动依赖注入。就是你不需要主动去声明构造函数IOC容器会自动帮你去使用构造函数。
举例
这里为了简单说明这里只使用单例自动装配举例。
namespace IOC_Test.Models
{public class Person{public int Id { get; set; }public string Name { get; set; }public int Age { get; set; } }
}
namespace IOC_Test.Services
{public class PersonService{public Person Person { get; set; }/// summary/// 无参构造函数/// /summarypublic PersonService() {Person new Person();}/// summary/// 有参构造函数IOC是选择尽可能多的参数构造/// /summary/// param nameperson/parampublic PersonService(Person person){this.Person person;}}
}
自动装配测试用例
using IOC_Test.Models;
using IOC_Test.Services;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;namespace IOC_Test
{internal class Program{static void Main(string[] args){IServiceCollection services new ServiceCollection();//注入依赖services.AddSingletonPerson();services.AddSingletonPersonService();//生成IOC容器var builder services.BuildServiceProvider();//两次打印第一次打印PersonService的Person{var res builder.GetServicePersonService();Console.WriteLine(JsonConvert.SerializeObject(res?.Person));}//修改Person,看看PersonService里面是不是会受影响{var res builder.GetServicePerson();res.Name 小王;res.Age 10;}//再次打印如果被修改那么就说明是自动装配。如果没被修改就说明没有将Person自动注入到PersonService{var res builder.GetServicePersonService();Console.WriteLine(JsonConvert.SerializeObject(res?.Person));}Console.WriteLine(Hello, World!);Console.ReadLine();}}
}
打印结果 自动装配执行顺序
测试用例
这里我们新建一个Dog
namespace IOC_Test.Models
{public class Dog{public int Id { get; set; }public string Name { get; set; }public int Age { get; set; }}
}Person
namespace IOC_Test.Models
{public class Person{public int Id { get; set; }public string Name { get; set; }public int Age { get; set; } }
}PersonService
namespace IOC_Test.Services
{public class PersonService{public Person Person { get; set; }public Dog Dog { get; set; }/// summary/// 无参构造函数/// /summarypublic PersonService() {Person new Person();}}
}
主函数
namespace IOC_Test
{internal class Program{static void Main(string[] args){IServiceCollection services new ServiceCollection();//注入依赖services.AddSingletonPerson();services.AddSingletonPersonService();services.AddSingletonDog();//生成IOC容器var builder services.BuildServiceProvider();//两次打印第一次打印PersonService{var res builder.GetServicePersonService();Console.WriteLine(JsonConvert.SerializeObject(res));}//修改Person和Dog,看看PersonService里面是不是会受影响{var person builder.GetServicePerson();person.Name 小王;person.Age 10;var dog builder.GetServiceDog();dog.Name 旺财;dog.Age 2;}//再次打印查看自动装配如何执行{var res builder.GetServicePersonService();Console.WriteLine(JsonConvert.SerializeObject(res));}Console.WriteLine(Hello, World!);Console.ReadLine();}}
}
有歧义构造函数
namespace IOC_Test.Services
{public class PersonService{public Person Person { get; set; }public Dog Dog { get; set; }/// summary/// 无参构造函数/// /summarypublic PersonService() {Person new Person();}public PersonService(Person person){this.Person person;}public PersonService(Dog dog) {this.Dog dog;}}
}如果构造函数出现歧义比如这里既可以选择Person构造又可以选择Dog构造会报错
渐进式构造函数
namespace IOC_Test.Services
{public class PersonService{public Person Person { get; set; }public Dog Dog { get; set; }/// summary/// 无参构造函数/// /summarypublic PersonService() {Person new Person();}public PersonService(Person person){this.Person person;}public PersonService(Person person,Dog dog) {this.Person person;this.Dog dog;}}
}运行成功
循环依赖
Person注入DogDog注入Person看看效果如何
namespace IOC_Test.Models
{public class Person{public Dog Dog { get; set; }public int Id { get; set; }public string Name { get; set; }public int Age { get; set; }public Person(Dog dog){Dog dog;}}
}namespace IOC_Test.Models
{public class Dog{public int Id { get; set; }public string Name { get; set; }public int Age { get; set; }public Person Person { get; set; }public Dog(Person person){Person person;}}
}自动装配结论
自动装配是尽可能主动去装配服务如果出现装配歧义循环依赖那么就会主动抛出异常。自动装配可以极大的减少对构造函数维护我们不需要知道服务是怎么声明的IOC容器会帮助我们自动声明相互之间的依赖。这张图就能很好的解释自动装配的效果 手动装配
自动装配是由IOC容器自动装配的类。如果需要装配多个同类的服务那就要手动进行区别了。
手动注入
internal class Program
{static void Main(string[] args){IServiceCollection services new ServiceCollection();services.AddSingletonPerson(sp {var res new Person() {Name 小红,Age 19};return res;});//生成容器var builder services.BuildServiceProvider();{var res builder.GetServicePerson();Console.WriteLine(JsonConvert.SerializeObject(res));}Console.WriteLine(Hello, World!);Console.ReadLine();}
}别名注入
namespace IOC_Test
{internal class Program{static void Main(string[] args){IServiceCollection services new ServiceCollection();services.AddKeyedSingletonPerson(A,(sp,key) {var res new Person() {Name 小红,Age 19};return res;});services.AddKeyedSingletonPerson(B, (sp, key) {var res new Person(){Name 小蓝,Age 23};return res;});//生成容器var builder services.BuildServiceProvider();//获取服务当Key找不到时自动返回Null{var res builder.GetServicePerson();Console.WriteLine(获取默认服务);Console.WriteLine(JsonConvert.SerializeObject(res));}{var res builder.GetKeyedServicePerson(A);Console.WriteLine(获取A,Person);Console.WriteLine(JsonConvert.SerializeObject(res));}{var res builder.GetKeyedServicePerson(B);Console.WriteLine(获取B,Person);Console.WriteLine(JsonConvert.SerializeObject(res));}Console.WriteLine(Hello, World!);Console.ReadLine();}}
} 声明别名的服务将不会自动装配即使声明的别名相同。建议使用多个不同名的服务来自动装配。手动声明别名需要手动装配对应关系 也可以在输入的时候主动拿到按照Key去寻找服务。
internal class Program
{static void Main(string[] args){IServiceCollection services new ServiceCollection();//依赖注入是使用的时候去构造所以声明顺序不影响实际运行顺序有点类似于回调函数services.AddKeyedSingletonPerson(A,(sp,key) {//Console.WriteLine(key);var res new Person() {Name 小红,Age 19};return res;});services.AddKeyedSingletonPersonService(A, (sp, key) {return new PersonService(sp.GetKeyedServicePerson(key));});//生成容器var builder services.BuildServiceProvider();//获取服务{var res builder.GetKeyedServicePerson(A);Console.WriteLine(获取默认服务);Console.WriteLine(JsonConvert.SerializeObject(res));}//获取服务{var res builder.GetKeyedServicePersonService(A);Console.WriteLine(获取默认服务);Console.WriteLine(JsonConvert.SerializeObject(res));}Console.WriteLine(Hello, World!);Console.ReadLine();}
}依赖注入的构造顺序
依赖注入是使用的时候去生成而不是注入的时候生成
namespace IOC_Test
{internal class Program{static void Main(string[] args){IServiceCollection services new ServiceCollection();services.AddKeyedSingletonPerson(A,(sp,key) {Console.WriteLine($构造函数执行,key[{key}]);var res new Person() {Name 小红,Age 19};return res;});//生成容器var builder services.BuildServiceProvider();//获取服务{Console.WriteLine(获取Key[A]服务);var res builder.GetKeyedServicePerson(A);Console.WriteLine(JsonConvert.SerializeObject(res));}Console.WriteLine(Hello, World!);Console.ReadLine();}}
} 结尾
IOC容器还有许多别的功能比如别名接口注入注解注入声明周期等。这个我还不太了解。现在的单例自动装配已经基本满足了我的功能我以后有时间会去深入了解。