【问题标题】:Clean way to Injecting dependency to wpf behavior将依赖项注入 wpf 行为的干净方法
【发布时间】:2015-10-13 08:13:04
【问题描述】:

我需要创建自定义 WPF 行为,并在 custructor 中注入一些依赖项,我不能使用构造函数注入,因为我需要在 XAML 中应用它,WPF 使用默认构造函数创建实例。 我可以做的一种方法是在默认构造函数或服务定位器中使用 Container,但我不想使用这些方法。 我可以在属性上使用 [Improt] 并使用 Container.SatisfyImportOnce 但不是很巧妙的方式,因为我仍将在构造函数中使用容器。 有什么建议吗?

我在我的 WPF 项目中使用 MEF 进行依赖注入。

简洁的方式:它应该是可测试的,我应该能够注入依赖项并且应该在 WPF XAML 中实例化。

【问题讨论】:

  • 不够具体。我相信您需要在定义中定义“整洁方式”的含义
  • 我想我明白你的问题是什么。尽管可以像他们在 DI 书中所说的那样做,但我建议不要仅仅因为它更“整洁”而使事情过于复杂。在某些情况和 API 中,您不能像使用自己的类(ctor 注入)那样简单地构建对象图。归根结底,这些骇人听闻的 DI 变通办法大多只是为了“正确”的 DI。但 DI 不是目标,而是工具。
  • 确实是视图的一部分,因为我们使用的是由工作区管理器管理的工作区并跟踪窗口,我们需要管理器将每个窗口注册到工作区管理器。同样在一个地方,我需要将小部件的大小保存到我的应用程序设置中,并且我想在多个地方使用相同的行为。用户可能会说我们希望我们的 UI 设置保留在数据库中,我可能需要您的建议。
  • 我怀疑您的整体架构设计存在问题。行为是视图的一部分,在 MVVM 中用于帮助视图显示非特定于应用程序的数据。让你的行为使用特定于应用程序的数据结构与代码隐藏本质上是一样的,并且通常很好地表明你的视图模型没有正确地完成它的工作。一个很好的例子是单元测试:DI 可以在你的虚拟机中进行,但是如果你只是在你的视图需要的行为中使用它,那就是浪费精力!

标签: c# wpf xaml dependency-injection mef


【解决方案1】:

您已经知道您不能使用 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 将:

  • 分析它所针对的属性类型(在示例中HtmlQueryHandlerIQueryHandler&lt;Query.Html, string&gt;
  • 从您正在使用的任何底层容器/解析器解析类型
  • 将其注入行为中。

【讨论】:

    猜你喜欢
    • 2013-09-06
    • 2011-08-19
    • 1970-01-01
    • 1970-01-01
    • 2013-01-13
    • 2015-01-19
    • 2021-07-11
    • 2016-10-01
    • 1970-01-01
    相关资源
    最近更新 更多