依赖注入并不意味着参数化的构造函数。事实上,如果你看 Unity 自带的示例,大部分依赖注入都是通过带有 [Dependency] 属性的属性来完成的。
Unity 与 XAML 配合得很好,但前提是您不使用参数化构造函数。使用具有 [Dependency] 属性的属性转换您的 UserControl 以获取其依赖项,您可以轻松使用 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 会更好。至少在开发大量依赖 Unity 进行依赖注入的代码之前,我会在测试应用程序上尝试纯 MVVM,看看它是如何工作的。