WPF 依赖注入 Microsoft.Extensions.DependencyInjection .NET
步骤 1: 添加必要的NuGet包
首先,确保项目中已经添加了必需的NuGet包。从你的.csproj文件来看,已经包含了以下相关的包:
Microsoft.Extensions.DependencyInjectionSerilog,Serilog.Sinks.File
步骤 2: 配置服务
在App.xaml.cs中配置服务集合。你已经在ConfigureServices方法中做了这项工作,包括注册服务、视图模型等。
private static IServiceProvider ConfigureServices()
{
var services = new ServiceCollection();
// 注册日志记录服务
services.AddSingleton<ILogger>(_ =>
{
return new LoggerConfiguration().MinimumLevel.Debug().WriteTo.File("log.txt").CreateLogger();
});
// 注册自定义服务
services.AddSingleton<IWebClient, WebClient>();
services.AddSingleton<ICatFactsService, CatFactsService>();
services.AddSingleton<IMessageBoxService, MessageBoxService>();
// 注册视图模型和服务
services.AddTransient<MainWindowViewModel>();
services.AddTransient<MainWindow>(sp => new MainWindow { DataContext = sp.GetService<MainWindowViewModel>() });
♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐
return services.BuildServiceProvider();
}
步骤 3: 初始化依赖注入容器
在App类的构造函数中初始化依赖注入容器,并将其分配给一个属性,以便稍后可以访问它。
public partial class App : Application
{
public static new App Current => (App)Application.Current;
public IServiceProvider Services { get; }
public App()
{
Services = ConfigureServices();
}
// ... 其他代码 ...
}
步骤 4: 使用依赖注入容器启动主窗口
在Application_Startup事件处理程序中,使用依赖注入容器获取并显示主窗口。
private void Application_Startup(object sender, StartupEventArgs e)
{
var mainWindow = Services.GetService<MainWindow>();
mainWindow!.Show();
}
步骤 5: 在XAML中声明Startup事件
确保在App.xaml中正确声明了Startup事件,这样当应用启动时会触发Application_Startup方法。
<Application x:Class="WpfIocDemo.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="Application_Startup">
</Application>
步骤 6: 确保所有组件都支持DI
确保所有的服务接口和实现以及视图模型都被设计为支持依赖注入的方式进行构造。例如,在你的MainWindowViewModel中,你应该通过构造函数注入所需的依赖项。
public MainWindowViewModel(ILogger logger, ICatFactsService catFactsService, IMessageBoxService messageBoxService)
{
_logger = logger;
this._catFactsService = catFactsService;
this._messageBoxService = messageBoxService;
_logger.Information("ViewModel Loaded.");
}
注入
using System;
using System.Windows;
using Microsoft.Extensions.DependencyInjection;
using Serilog;
using WpfIocDemo.Services;
namespace WpfIocDemo;
public partial class App : Application
{
/// <summary>
/// Gets the current <see cref="App"/> instance in use
/// </summary>
public static new App Current => (App)Application.Current;
♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐
/// <summary>
/// Gets the <see cref="IServiceProvider"/> instance to resolve application services.
/// </summary>
public IServiceProvider Services { get; }
♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐
public App()
{
♈♈♈♈♈♈♈
Services = ConfigureServices();
}
♈♈♈♈♈♈♈
private static IServiceProvider ConfigureServices()
{
var services = new ServiceCollection();
services.AddSingleton<ILogger>(_ =>
{
return new LoggerConfiguration().MinimumLevel.Debug().WriteTo.File("log.txt").CreateLogger();
});
services.AddSingleton<IWebClient, WebClient>();
services.AddSingleton<ICatFactsService, CatFactsService>();
services.AddSingleton<IMessageBoxService, MessageBoxService>();
services.AddTransient<MainWindowViewModel>();
services.AddTransient<MainWindow>(sp => new MainWindow { DataContext = sp.GetService<MainWindowViewModel>() });
return services.BuildServiceProvider();
}
private void Application_Startup(object sender, StartupEventArgs e)
{
var mainWindow = Services.GetService<MainWindow>();
mainWindow!.Show();
}
}
使用
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Serilog;
using WpfIocDemo.Services;
namespace WpfIocDemo;
partial class MainWindowViewModel : ObservableObject
{
[ObservableProperty]
string title = "CatFacts";
private ILogger _logger;
private readonly ICatFactsService _catFactsService;
private readonly IMessageBoxService _messageBoxService;
public ObservableCollection<string> CatFacts { get; } = new();
public MainWindowViewModel(ILogger logger, ICatFactsService catFactsService, IMessageBoxService messageBoxService)
{ ♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐♐
_logger = logger;
this._catFactsService = catFactsService;
this._messageBoxService = messageBoxService;
_logger.Information("ViewModel Loaded.");
}
[RelayCommand]
async Task GetFacts(string text)
{
if (int.TryParse(text, out var limit))
{
if (limit <= 0)
{
_messageBoxService.ShowMessage("输入的 limit 值应该大于 0!");
return;
}
var facts = await _catFactsService.GetCatFactsAsync(limit);
foreach (var fact in facts)
{
CatFacts.Add(fact);
}
}
else
{
_messageBoxService.ShowMessage("输入的 limit 值不对!");
}
}
}
浙公网安备 33010602011771号