La inyección de dependencias no implica constructores parametrizados. De hecho, si observa las muestras que vienen con Unity, la mayor parte de la inyección de dependencia se realiza por propiedades con el atributo [Dependency].
Unity funciona muy bien con XAML, pero solo si no utiliza constructores parametrizados. Convierta su UserControl para tomar sus dependencias usando propiedades con el atributo [Dependency], y puede usar XAML fácilmente.
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));
...
}
Tenga en cuenta que una [Dependencia] propiedad puede ser declarado ya sea como una propiedad de dependencia o como una propiedad CLR llano, como se muestra arriba. Esto suena como una nomenclatura confusa, pero en la práctica es muy simple.
Para especificar el UnityContainer en XAML y obtener la configuración automática, basta con crear una propiedad adjunta heredada "UnityHelper.Container" cuya PropertyChangedCallback simplemente llama a la acumulación en el contenedor especificado y pasa en el tipo de objeto y el objeto:
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);
}
}
});
}
Ahora se puede asignar un UnityContainer a la ventana de su raíz y toda su aplicación va a usar, por ejemplo, usted podría hacerlo en el constructor de la ventana de la siguiente manera:
UnityHelper.SetContainer(this, new UnityContainer() ...);
O puede asignar el contenedor de la unidad usando XAML en cualquier nivel deseado del árbol:
<UserControl ...
my:UnityHelper.Container="{DynamicResource MainUnityContainer}" />
Habiendo dicho todo esto, pienso que usted encontrará que las características y diccionarios de recursos de enlace de datos avanzadas de WPF juntos eliminan el 98% de las razones por las que una Es posible que la persona quiera usar Unity en primer lugar. Puede que a la larga sea mejor alejarse de Unity e ir con MVVM simple. Por lo menos, probaría MVVM puro en una aplicación de prueba para ver cómo funciona antes de desarrollar mucho código confiando en Unity para la inyección de dependencia.
funciona, pero cuando pulso el botón de pestaña de uno de los cuadro de texto que arroja una excepción Resolución de la dependencia fracasó, type = "+ System.Windows.Input.KeyboardNavigation FocusVisualAdorner", name = "". El mensaje de excepción es: La operación de compilación actual (clave de compilación clave Build [System.Windows.Input.KeyboardNavigation + FocusVisualAdorner, null]) falló: no se pudo cargar el tipo 'System.Windows.Input.KeyboardNavigation' desde el ensamblado 'PresentationFramework, Version = 3.0 .0.0, Cultura = neutral, PublicKeyToken = 31bf3856ad364e35 '. (Tipo de estrategia BuildPlanStrategy, índice 5) – Miral
Esta respuesta me ayudó muchísimo. Ojalá pudiera dar más de +1. He agregado este hilo a "Mis favoritos", pero eso solo acredita al tipo que hizo la pregunta original. ¡Así que gracias! – Tormod
Si crea una interfaz (digamos llamada IUnityElement) que aplique a todos sus UserControls o Controls, necesita ejecutar la unidad en la línea 'if (container! = Null)', puede verificar si el parámetro obj es de esa interfaz p.ej 'if (contenedor! = nulo && obj es IUnityInject)'. Esto elimina el error que Miral comentó anteriormente (obtuve uno similar de un objeto diferente y el problema de rendimiento de la respuesta de ZeePrime, ya que BuildUp solo se ejecuta en FrameworkElements que lo necesite). –