在WPF中使用.NET Core 3.0依赖项注入和服务提供程序

在WPF中使用.NET Core 3.0依赖项注入和服务提供程序

Posted by Walter Gao on October 29, 2019

前言

我们都知道.NET Core提供了对依赖项注入的内置支持。我们通常在ASP.NET Core中使用它(从Startup.cs文件中的ConfigureServices方法开始),但是该功能不限于此框架,我们可以在WPF和Windows Forms应用程序中使用它。

实践

  1. 新建项目

    1572333532.jpg

  2. 将所需的NuGet包添加到项目中。

    • Microsoft.Extensions.DependencyInjection
    • Microsoft.Extensions.Options.ConfigurationExtensions
    • Microsoft.Extensions.Configuration.Json 1572334178_1_.jpg
  3. 然后,将一个名为appsettings.json的文件添加到项目的根文件夹。将其“ 构建操作”属性设置为“ 内容”,将“复制到输出目录”设置为“ 复制”(如果较新):

     {
     "AppSettings": {
         "AppName": "SampleNetCore3WpfDependencyInjection"
         }
     }
    
  4. 创建一个AppSettings.cs文件来保存配置设置。该文件将映射我们在appsettings.json中编写的设置:

     public class AppSettings
         {
             public string AppName { get; set; } 
         }
    
  5. 创建一个示例服务:

     public interface ISampleService
         {
             Task<string> GetCurrentDate();
         }
    
     public class SampleService : ISampleService
         {
             public async Task<string> GetCurrentDate() => 
             await Task.FromResult(DateTime.Now.ToLongDateString());
         }
    

    然后像往常一样在IOC容器中注册服务:

     services.AddScoped<ISampleService, SampleService>();
    
  6. 打开App.xaml文件并删除Application类的StartupUri属性。然后,我们需要重写App.xaml.cs中的OnStartup方法:

     public partial class App : Application
         {
             public IServiceProvider ServiceProvider { get; private set; }
             public IConfiguration Configuration { get; private set; }
    
             protected override void OnStartup(StartupEventArgs e)
             {
                 var builder = new ConfigurationBuilder()
                     .SetBasePath(Directory.GetCurrentDirectory())
                     .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
    
                 Configuration = builder.Build();
    
                 var serviceCollection = new ServiceCollection();
                 ConfigureServices(serviceCollection);
    
                 ServiceProvider = serviceCollection.BuildServiceProvider();
    
                 var mainWindow = ServiceProvider.GetRequiredService<MainWindow>();
                 mainWindow.Show();
             }
    
             private void ConfigureServices(IServiceCollection services)
             {
                 services.Configure<AppSettings>(Configuration.GetSection(nameof(AppSettings)));
                 services.AddScoped<ISampleService, SampleService>();
                 services.AddTransient(typeof(MainWindow));
             }
         }
    
  7. MainWindow简单布局及代码改造

    如上所述,MainWindow位于IOC容器中。因此,当我们从服务提供商处获得服务时,它将自动注入所有必需的服务(如果有)。:

     public partial class MainWindow : Window
         {
             private readonly ISampleService sampleService;
             private readonly AppSettings settings;
    
             public MainWindow(ISampleService sampleService,
                 IOptions<AppSettings> settings)
             {
                 InitializeComponent();
    
                 this.sampleService = sampleService;
                 this.settings = settings.Value;
             }
    
             private async void Button_Click(object sender, RoutedEventArgs e)
             {
                 var serviceData =await sampleService.GetCurrentDate();
                 var settingsData = settings;
                 TextBox1.Text = $"serviceData:{serviceData}{Environment.NewLine}settingsData:{settings.AppName}";
             }
         }
    

    1572335382_1_.jpg