向wpf行为注入依赖的干净方式
本文关键字:方式 依赖 注入 wpf | 更新日期: 2023-09-27 18:17:20
我需要在构造函数中注入一些依赖项来创建自定义WPF行为,我不能使用构造函数注入,因为我需要在XAML中应用它,WPF使用默认构造函数创建实例。我可以做的一种方法是在默认构造函数或服务定位器中使用Container,但我不想使用这些方法。我可以在属性上使用[import]并使用Container。SatisfyImportOnce但不是很整洁的方式,因为我仍然会在构造函数中使用容器。任何建议吗?
我在WPF项目中使用MEF进行依赖注入。
整洁的方式:它应该是可测试的,我应该能够注入依赖,并且应该在WPF XAML中实例化。
正如你已经知道的,你不能用Wpf进行构造函数注入,但是你可以在Xaml中定义属性注入。我认为一个"整洁"的解决方案是使用MarkupExtension
,如:
public sealed class Resolver : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
var provideValueTarget = (IProvideValueTarget)serviceProvider
.GetService(typeof(IProvideValueTarget));
// Find the type of the property we are resolving
var targetProperty = provideValueTarget.TargetProperty as PropertyInfo;
if (targetProperty == null)
{
throw new InvalidProgramException();
}
// Find the implementation of the type in the container
return BootStrapper.Container.Resolve(targetProperty.PropertyType);
}
}
和这样的行为:
public sealed class InitialiseWebBrowser : Behavior<MyVM>
{
public IQueryHandler<Query.Html, string> HtmlQueryHandler { private get; set; }
// ...
}
我们可以这样配置Xaml中的属性注入:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
xmlns:inf="clr-namespace:abc"
xmlns:behaviours="clr-namespace:def"
x:Class="MyVM">
<i:Interaction.Behaviors>
<behaviours:InitialiseWebBrowser HtmlQueryHandler="{inf:Resolver}"/>
</i:Interaction.Behaviors>
Resolver
MarkupExtension将:
- 分析它所定义的属性的类型(在示例中
HtmlQueryHandler
是IQueryHandler<Query.Html, string>
) - 从您正在使用的任何底层容器/解析器中解析类型
- 将其注入到行为中。