IOC在Web API 中是经常使用的,但是在一些WPF项目并不是经常使用或者被人熟知的,我把相关依赖注入的内容又做了一次学习和整理
依赖注入是一种设计模式和软件设计原则,用于实现 控制反转。它的核心思想是:将对象所依赖的其他对象的创建和管理职责从对象内部转移到外部容器或框架,从而降低代码的耦合度,提高可测试性、可维护性和灵活性。
● Microsoft.Extensions.DependencyInjection.Abstractions
● Microsoft.Extensions.Dependencyinjection
● IServiceCollection 服务注册
● ServiceDescriptor 服务注册时的信息
● IServiceProvider 具体的容器
● IServiceScope 子容器生命周期
● 在整个进程中,多次创建对象都是同一个对象—遵循了单例模式;
● 第一次创建以后,在内存中,保存下来了,下次创建–直接使用内存,而不是再去全新的创建
ServiceCollection serviceDescriptors = new ServiceCollection();
serviceDescriptors.AddSingleton<ITestService, TestService>();
ServiceProvider serviceProvider = serviceDescriptors.BuildServiceProvider();
ITestService testService1 = serviceProvider.GetService<ITestService>();
ITestService testService2 = serviceProvider.GetService<ITestService>();
bool isflg = object.ReferenceEquals(testService1, testService2);
Console.WriteLine($"testService1==testService2 {isflg}"); //true
● 每一个作用域(serviceProvider)内创建的某一个类的对象是同一个实例
● 不同的作用域(serviceProvider)内创建的同一个类的对象是不同的实例
● 这种⽣命周期适⽤于需要在特定作⽤域内共享对象实例的情 况,⽐如Web应⽤程序中的每个HTTP请求
ServiceCollection serviceDescriptors = new ServiceCollection();
serviceDescriptors.AddScoped<ITestService, TestService>();
ServiceProvider serviceProvider1 = serviceDescriptors.BuildServiceProvider();
ITestService testService1 = serviceProvider1.GetService<ITestService>();
ITestService testService2 = serviceProvider1.GetService<ITestService>();
bool isflg = object.ReferenceEquals(testService1, testService2);
Console.WriteLine($"testService1==testService2 {isflg}");//true
ServiceProvider serviceProvider2 = serviceDescriptors.BuildServiceProvider();
ITestService testService3 = serviceProvider2.GetService<ITestService>();
ITestService testService4 = serviceProvider2.GetService<ITestService>();
bool isflg1 = object.ReferenceEquals(microphone3, microphone4);
Console.WriteLine($"testService3==testService4 {isflg1}");//true
bool isflg2 = object.ReferenceEquals(testService1, testService3);
Console.WriteLine($"microphone1==microphone3 {isflg2}");//false
● 每一次都会创建出一个全新的实例
● 如果需要每次都创建实例—瞬时
ServiceCollection serviceDescriptors = new ServiceCollection();
serviceDescriptors.AddTransient<ITestService, Microphone>();
ServiceProvider serviceProvider = serviceDescriptors.BuildServiceProvider();
ITestService testService1 = serviceProvider.GetService<ITestService>();
ITestService testService2 = serviceProvider.GetService<ITestService>();
bool isflg = object.ReferenceEquals(testService1, testService2);
Console.WriteLine($"testService1==testService2 {isflg}"); //fals
在执行构造函数的时候,能够把构造函数依赖的参数自动构造出来,传递进来;–无限层级
public class MainViewModel
{
private readonly ITestService _testService;
public MainViewModel(ITestService testService)
{
this._testService = testService;
}
}
在某个类的内部包含的有属性,在构造出整个类的时候,这个类中的某些属性,能够自动根据属性的类型–自动构造出实例–赋值给属性;
官方不支持需要引入第三方框架
public class MainViewModel
{
[Inject]
public ITestService TestService { get; set; }
public MainViewModel()
{
}
}
在某个类的内部,包含的有一些特殊的方法,在构造这个类的实例的时候,能够自动的把方法执行掉,方法需要的参数—自动构建实例,传递进来;
• [FromServices] 需要引用 NuGet 包:Microsoft.AspNetCore.Mvc(仅限 ASP.NET Core 项目)。
public class MainViewModel
{
public MainViewModel()
{
}
public void Test([FromServices] ITestService testService)
{
testService.GetMessage();
}
}
public partial class App : Application
{
public static App CurrentApp { get; private set; } = null!;
public App()
{
CurrentApp = this;
}
public IServiceProvider ServiceProvider { get; set; } = null!;
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
this.ServiceProvider = serviceCollection.BuildServiceProvider();
var mainWindow = this.ServiceProvider.GetService<MainWindow>();
mainWindow?.Show();
}
private void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<MainWindow>();
services.AddSingleton<MainViewModel>();
services.AddTransient<ITestService, TestService>();
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = App.CurrentApp.ServiceProvider.GetService(typeof(MainViewModel));
}
}