如何使用Simple Injector依赖项的WPF控件

Rob*_*tto 5 c# wpf dependency-injection simple-injector

我想在我必须将资源注入GUI控件的场景中使用依赖注入.由于这可能是错误的地方,我有一些理由在这里做而不是在视图模型中(例如,我需要Window句柄等).

构造函数参数注入似乎是首选方式.正如大多数人所知,WPF控件必须具有无参数构造函数,否则XAML不起作用,对于当前场景,我喜欢保留我的XAML,因为它包含一些名称注册和绑定.

那么:我如何在WPF + XAML场景中使用构造函数-DI(如果可能的话,在Simple Injector的情况下)?

是否存在标记扩展,或者XAML解析器是否可以成为Container-Aware并接受具有参数的构造函数作为控件?

方案示例:

<Grid>
 <gg:WhateverResourceNeedingViewer ItemSource={Binding Items}/>
</Grid>
Run Code Online (Sandbox Code Playgroud)

和:

public class WhateverResourceNeedingViewer : ItemsControl
{
   public WhateverResourceNeedingViewer(Dep1 d, DepResource d2)
   {
   ...
   }
...
}
Run Code Online (Sandbox Code Playgroud)

Ric*_*Net 6

优良作法不仅是使用SOLID设计原则构建视图模型,还要在视图中执行此操作.usercontrols的使用可以帮助您解决这个问题.

如果技术上可行的话,您建议的方法的缺点是此设计将违反SRPOCP.

SRP,因为必须在使用窗口/视图中注入usercontrol所需的所有依赖项,而此视图可能不需要(全部)这些依赖项.

和OCP因为每次从usercontrol添加或删除依赖项时,您还需要在使用窗口/视图中添加或删除它.

使用usercontrols,您就可以像编写其他类(如服务,命令和查询处理程序等)一样编写视图.当涉及到依赖项注入时,编写应用程序的位置就是组合根

WPF中的ContentControl都是关于从应用程序中的其他"内容""组合"您的视图.

Caliburn Micro这样的MVVM工具通常使用内容控件将自己的viewmodel注入一个usercontrol视图(读取:xaml,不带代码).事实上,在使用MVVM时,您将从usercontrols类构建应用程序中的所有视图,这是最佳实践.

这看起来像这样:

public interface IViewModel<T> { }

public class MainViewModel : IViewModel<Someclass>
{
    public MainViewModel(IViewModel<SomeOtherClass> userControlViewModel)
    {
        this.UserControlViewModel = userControlViewModel;
    }

    public IViewModel<SomeOtherClass> UserControlViewModel { get; private set; }
}

public class UserControlViewModel : IViewModel<SomeOtherClass>
{
    private readonly ISomeService someDependency;

    public UserControlViewModel(ISomeService someDependency)
    {
        this.someDependency = someDependency;
    }
}
Run Code Online (Sandbox Code Playgroud)

和MainView的XAML:

// MainView
<UserControl x:Class="WpfUserControlTest.MainView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
        <ContentControl Name="UserControlViewModel" />
    </Grid>
</UserControl>

// UserControl View
<UserControl x:Class="WpfUserControlTest.UserControlView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
        <TextBlock Text="SomeInformation"/>
    </Grid>
</UserControl>
Run Code Online (Sandbox Code Playgroud)

结果将MainView显示在该窗口的DataContext窗口设置为的窗口中MainViewModel.contentcontrol将UserControlView使用其DataContext设置为UserControlViewModel类填充.这是自动发生的,因为MVVM工具将使用Convention over configuration将视图模型绑定到相应的视图.

如果您不使用MVVM工具但直接在窗口类的代码中注入依赖项,则只需遵循相同的模式即可.在视图中使用ContentControl,就像上面的示例一样,并UserControl在窗口的构造函数中注入(带有包含参数的构造函数).然后只需将ContentContentControl 的属性设置为UserControl的注入实例.

那看起来像是:

public partial class MainWindow : Window
{
    public MainWindow(YourUserControl userControl)
    {
        InitializeComponent();
        // assuming you have a contentcontrol named 'UserControlViewModel' 
        this.UserControlViewModel.Content = userControl;
    }

    // other code...
}
Run Code Online (Sandbox Code Playgroud)