背景
项目开发到现在,越来越多的ViewModel对象,需要对象便New,传递对象通过构造函数或属性,使得代码的耦合性越来越大。
想到能否有一个容器统一的管理对象???
需要的时候就直接从容器中取就行,切容器的对象是自动管理依赖关系的,就像Java语言中的SpringIOC一样。
发现Microsoft.Extensions.DependencyInjection正好解决了这个问题,于是便有了下文。
使用方法:
添加Microsoft.Extensions.DependencyInjection到项目中,使用NuGet管理器或者命令行;
关键代码:
- 添加服务管理类,用于全局管理对象示例:
using Microsoft.Extensions.DependencyInjection;
using System;
namespace abc.Services;
public static class ServiceLocator
{
private static IServiceProvider _serviceProvider;
public static void Initialize(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public static T GetService<T>() where T : class
{
return _serviceProvider.GetService<T>();
}
}
- 添加对象注入到容器中;
private IServiceProvider? _provider;
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
_provider = ConfigureServices();
// 初始化服务定位器
ServiceLocator.Initialize(_provider);
}
public override void OnFrameworkInitializationCompleted()
{
var viewLocator = _provider?.GetRequiredService<IDataTemplate>();
var mainViewModel = _provider?.GetRequiredService<MainViewModel>();
var mainWindow = _provider?.GetRequiredService<MainWindow>();
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = mainWindow;
}
else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform)
{
singleViewPlatform.MainView = new MainView1
{
DataContext = mainViewModel
};
}
base.OnFrameworkInitializationCompleted();
}
private static ServiceProvider ConfigureServices()
{
var viewLocator = Current?.DataTemplates.First(x => x is ViewLocator);
var services = new ServiceCollection();
// Views
services.AddSingleton<MainWindow>();
// Services
if (viewLocator is not null)
services.AddSingleton(viewLocator);
// ViewModels
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => !p.IsAbstract && typeof(ViewModelBase).IsAssignableFrom(p));
foreach (var type in types)
{
services.AddSingleton(type);
}
return services.BuildServiceProvider();
}
public class OneViewModel : ViewModelBase{}
public class TwoViewModel : ViewModelBase{}
public class ThreeViewModel : ViewModelBase{}
...
前后代码对比:
可见,对比结果一目了然,不仅代码简洁了而且还解耦了。
深潜:
- 除了通过构造函数的方式注入,是否能通过注解的方式注入对象呢?比如像Spring中的@AutoWired?
- 在使用的过程中发现AvaloniaEdit.Utils包下同样包含ServiceCollection,那是否Avalonia11本来就包含对象管理容器而不需要引入三方的轮子呢?
- 使用时注意循环嵌套问题,如果程序一直加载不完最终内存溢出,那多半就是循环依赖了,检查对象依赖关系,不能A->B->C->A这样。
总结:
- 介绍了Microsoft DI的使用方法,当然同类的轮子还有好多,选择微软,是因为开发语言和使用的.Net Core都是一家;
- 添加的服务管理类ServiceLocator使得在其他对象中使用另外对象变的很方便,同时也降低了New对象造成的耦合性;
本文完。