WPF的.NET Core 3.0中的依赖项注入

时间:2019-02-26 01:55:11

标签: wpf .net-core .net-core-3.0

我对ASP.NET Core和对依赖项注入的支持非常熟悉。控制器可以通过在其构造函数中添加参数来要求依赖关系。如何在WPF UserControls中实现依赖关系?我尝试向构造函数添加参数,但这没用。我喜欢IOC的概念,希望将其推广到WPF。

5 个答案:

答案 0 :(得分:3)

我最近在我的项目中遇到了这个要求,并以此方式解决了这个问题。

用于WPF的.NET Core 3.0中的依赖项注入。在解决方案中创建WPF core 3项目之后,您需要安装/添加nuget软件包:

Microsoft.Extensions.DependencyInjection

在我的情况下,我创建了一个用于日志记录的类,称为LogBase,因此在您的App类中添加以下内容,而这仅仅是一个基本示例:

private readonly ServiceProvider _serviceProvider;

public App()
{
    var serviceCollection = new ServiceCollection();
    ConfigureServices(serviceCollection);
    _serviceProvider = serviceCollection.BuildServiceProvider();
}

private void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<ILogBase>(new LogBase(new FileInfo($@"C:\temp\log.txt")));
    services.AddSingleton<MainWindow>();
}

private void OnStartup(object sender, StartupEventArgs e)
{
    var mainWindow = _serviceProvider.GetService<MainWindow>();
    mainWindow.Show();
}

在您的App.xaml中,添加Startup =“ OnStartup”,如下所示:

<Application x:Class="VaultDataStore.Wpf.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:VaultDataStore.Wpf"
             Startup="OnStartup">
    <Application.Resources>

    </Application.Resources>
</Application>

因此,在MainWindow.xaml.cs中,将ILogBase注入构造函数中,如下所示:

private readonly ILogBase _log;

public MainWindow(ILogBase log)
{
    _log = log;

    ...etc.. you can use _log over all in this class

在LogBase类中,我使用自己喜欢的任何记录器。

我在operator precedence回购中将所有这些内容加在一起。

答案 1 :(得分:1)

在WPF中,您使用称为Model-View-ViewModel(简称MVVM)的模式。您的依赖项被注入到视图模型中(使用与在ASP.NET中使用的相同的IoC框架,例如AutoFac),并且您的视图(UserControls)被注册为视图模型的数据模板。

通过这种方式,您可以围绕视图模型构建应用程序,并像视图模型依赖于视图一样解析视图(取决于视图模型)。视图可以通过其DataContext属性访问其视图模型。因此,您可以将视图模型用作外观,以向视图中注入任何内容。

答案 2 :(得分:0)

通常来说,您不会。您可以在视图模型中使用依赖注入,然后使用数据绑定将视图绑定到视图。

这并不是说它不能完成。例如,MVVM Light创建一个注入器类,然后在App.xaml中声明其实例,这与声明全局变量几乎相同:

<Application.Resources>
    <ResourceDictionary>
        <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" xmlns:vm="clr-namespace:MyMvvmProject.ViewModel" />
    </ResourceDictionary>
</Application.Resources>

作为可视树一部分的Windows和用户控件可以绑定到应用程序资源,因此在该框架中,主窗口通常像这样绑定到视图模型:

<Window x:Class="MyMvvmProject.MainWindow"
    ...
    DataContext="{Binding Source={StaticResource Locator}, Path=Main}">

...其中Main是locator类的属性:

public MainViewModel Main
{
    get
    {
        return ServiceLocator.Current.GetInstance<MainViewModel>();
    }
}

这不是很好的IoC,因为它将所有注射剂都放在一个类中,实际上,您会将其分解为各个级别的专门工厂等。

但认真的说,不要做任何事情。在视图模型层中使用DI,并使用宽松的数据绑定将其耦合到视图。这将使您能够充分利用依赖项注入的功能,部分是通过将其从不需要的层中分离出来,部分是通过灵活地针对不同的环境(例如,Web,桌面,移动和特别是单元测试)重新配置依赖项根本不会创建视图的地方。

(免责声明:我尚未将.NET Core用于WPF,所以我在这里介绍的内容可能是.NET特定的,但是一般原理仍然存在。)

答案 3 :(得分:0)

好问题,如果没有在xaml中使用非参数化构造函数的控件,将无法使用。如果需要,您需要从代码中实例化它,但是xaml不会调用该构造函数。

答案 4 :(得分:0)

在这种情况下,您必须使用背后的代码。但是请三思,如果真的有必要在UserControl或从xaml实例化的任何其他类中具有依赖项。