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)
优良作法不仅是使用SOLID设计原则构建视图模型,还要在视图中执行此操作.usercontrols的使用可以帮助您解决这个问题.
如果技术上可行的话,您建议的方法的缺点是此设计将违反SRP和OCP.
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)