带参数化构造函数的wpf usercontrol

时间:2010-04-30 11:55:20

标签: wpf user-controls unity-container

我们正在使用Microsoft Unity和依赖注入,因此我们为usercontrol提供了参数化构造函数。如何使用XAML将此依赖项注入usercontrol?

我在XAML中添加了usercontrol,如下所示。

xmlns:usrRefundArrivalProcessor="Ttl.Refunds.Wpf.Dashboad.Application.Usercontrols;assembly=Ttl.Refunds.Wpf.Dashboad.Application"

3 个答案:

答案 0 :(得分:10)

依赖注入并不意味着参数化构造函数。实际上,如果查看Unity附带的示例,大多数依赖注入都是通过具有[Dependency]属性的属性完成的。

Unity与XAML非常兼容,但前提是您不使用参数化构造函数。转换您的UserControl以使用具有[Dependency]属性的属性获取其依赖项,并且您可以轻松使用XAML。

public class MyUserControl : UserControl
{
  [Dependency]
  public ISomething Something { get; set; }

  [Dependency]
  public IWhatever Whatever { get { return (IWhatever)GetValue(WhateverProperty); } set { SetValue(WhateverProperty, value); }
  public readonly DependencyProperty WhateverProperty = DependencyProperty.Register("Whatever", typeof(IWhatever), typeof(MyUserControl));

  ...
}

请注意,[Dependency]属性可以声明为DependencyProperty或纯CLR属性,如上所示。这听起来像是令人困惑的命名法,但在实践中它很简单。

要在XAML中指定UnityContainer并获得自动配置,只需创建一个继承的附加属性“UnityHelper.Container”,其PropertyChangedCallback只是在指定的容器上调用BuildUp并传入对象的类型和对象:

public class UnityHelper
{
  public static IUnityContainer GetContainer(DependencyObject obj) { return (IUnityContainer)obj.GetValue(ContainerProperty); }
  public static void SetContainer(DependencyObject obj, IUnityContainer value) { obj.SetValue(ContainerProperty, value); }
  public static readonly DependencyProperty ContainerProperty = DependencyProperty.RegisterAttached("Container", typeof(IUnityContainer), typeof(UnityHelper), new FrameworkPropertyMetadata
  {
    Inherits = true,
    PropertyChangedCallback = (obj, e) =>
    {
      var container = e.NewValue as IUnityContainer;
      if(container!=null)
      {
        var element = obj as FrameworkElement;
        container.BuildUp(obj.GetType(), obj, element==null ? null : element.Name);
      }
    }
  });
}

现在您可以将UnityContainer分配给根窗口,整个应用程序将使用它,例如您可以在窗口的构造函数中执行此操作,如下所示:

UnityHelper.SetContainer(this, new UnityContainer() ...);

或者您可以在树的任何所需级别使用XAML分配统一容器:

<UserControl ...
  my:UnityHelper.Container="{DynamicResource MainUnityContainer}" />

说了这么多,我想你会发现WPF的高级数据绑定功能和资源词典一起消除了一个人可能想要首先使用Unity的98%的原因。从长远来看,你可能会发现它更好地远离Unity并使用简单的MVVM。至少我会在测试应用程序上尝试纯MVVM,看看在开发依赖Unity依赖注入的代码之前它是如何工作的。

答案 1 :(得分:0)

似乎很容易。为什么不简单地向您的UserControl添加“公共无参数构造函数”?您可以选择不直接在代码中使用它,但这正是Designer所寻求的。如果要确保从未在代码中调用它,请放置a check for presence of Designer并在未检测到Designer时抛出异常。

答案 2 :(得分:0)

它可以工作,但是当你使用网格或复杂的WPF屏幕时性能非常差。 Inherits = true意味着创建的所有GUI元素都将具有在构造函数之后调用的附加属性的PropertyChangedCallback,即使该特定GUI元素根本不需要Unity。 当你有网格时,每当出现一个新行时,就会动态创建所有GUI元素,并调用该回调。 这是我们网格的杀戮性能,因此我们不得不以这种方式删除UnityInjection。

但是有些地方我们需要在代码隐藏中使用UnityInjection,即使我们使用MVVM,我们也没有找到解决这个问题的好方法。 一些复杂的用户控件是使用MVVM设计的,其中控件的ViewModel由控件本身的代码隐藏创建,该控件由使用该控件的XAML创建。 在这种特定情况下,控件的ViewModel对Unity没有任何了解,但我们需要在其中使用unity注入,以访问注册的外部资源。