Внедрение зависимостей не подразумевает параметризованные конструкторы. Фактически, если вы посмотрите на примеры, которые поставляются с 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, как показано выше. Это звучит как запутанная номенклатура, но на практике это очень просто.
Чтобы указать UnityContainer в XAML и получить автоматическую настройку, просто создайте унаследованное вложенное свойство «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 и словари ресурсов вместе устраняют 98% причин, по которым человек может захотеть использовать Unity. Возможно, в конечном итоге вам будет лучше отойти от Unity и перейти на простой MVVM. По крайней мере, я бы попробовал чистый MVVM в тестовом приложении, чтобы увидеть, как оно работает, прежде чем разрабатывать много кода, использующего Unity для внедрения зависимостей.