L'injection de dépendances n'implique pas de constructeurs paramétrés. En fait, si vous examinez les exemples fournis avec Unity, la plus grande partie de l'injection de dépendance est effectuée par des propriétés avec l'attribut [Dependency]. L'unité fonctionne très bien avec XAML, mais seulement si vous n'utilisez pas de constructeurs paramétrés. Convertissez votre UserControl pour prendre ses dépendances en utilisant des propriétés avec l'attribut [Dependency], et vous pouvez facilement utiliser 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));
...
}
Notez qu'une propriété [dépendance] peut être déclarée soit comme DependencyProperty ou comme une propriété CLR plaine, comme indiqué ci-dessus. Cela ressemble à une nomenclature confuse, mais en pratique, c'est très simple.
Pour spécifier le UnityContainer en XAML et obtenir la configuration automatique, il suffit de créer une joint propriété « UnityHelper.Container » héritée dont PropertyChangedCallback appelle simplement colmatages sur le conteneur spécifié et passe dans le type de l'objet et l'objet:
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);
}
}
});
}
maintenant, vous pouvez attribuer un UnityContainer à votre fenêtre racine et votre application entière utiliser, par exemple, vous pouvez le faire dans le constructeur de la fenêtre comme suit:
UnityHelper.SetContainer(this, new UnityContainer() ...);
Ou vous pouvez assigner le récipient d'unité à l'aide XAML à tout niveau souhaité de l'arbre:
<UserControl ...
my:UnityHelper.Container="{DynamicResource MainUnityContainer}" />
Ayant dit tout cela, je pense que vous trouverez que les données avancées de WPF fonctions de liaison et les dictionnaires de ressources éliminent ensemble 98% des raisons pour lesquelles une personne pourrait vouloir utiliser Unity en premier lieu. Vous trouverez peut-être mieux à long terme pour s'éloigner de l'unité et aller avec MVVM simple. À tout le moins, j'essaierais MVVM pur sur une application de test pour voir comment cela fonctionne avant de développer beaucoup de code en se basant sur Unity pour l'injection de dépendance.
cela fonctionne, mais quand je clique sur le bouton onglet d'un de la zone de texte, il émet une exception Résolution de la dépendance a échoué, type = « System.Windows.Input.KeyboardNavigation + FocusVisualAdorner », name = « ». Le message d'exception est: L'opération de génération en cours (clé de construction Build Key [System.Windows.Input.KeyboardNavigation + FocusVisualAdorner, null]) a échoué: Impossible de charger le type 'System.Windows.Input.KeyboardNavigation' à partir de l'assembly 'PresentationFramework, Version = 3.0 .0.0, Culture = neutral, PublicKeyToken = 31bf3856ad364e35 '. (Type de stratégie BuildPlanStrategy, index 5) – Miral
Cette réponse m'a énormément aidé. J'aimerais pouvoir donner plus de +1. J'ai ajouté ce fil à "Mes favoris", mais cela ne fait que créditer le gars qui pose la question originale. Alors merci! – Tormod
Si vous créez une interface (par exemple appelée IUnityElement) que vous appliquez à tous vos UserControls ou Contrôles, vous devez exécuter unit sur alors dans la ligne 'if (container! = Null)' vous pouvez vérifier si le paramètre obj est de cette interface par exemple 'if (conteneur! = null && obj est IUnityInject)'. Ceci élimine l'erreur que Miral a commentée plus haut (j'en ai obtenu une similaire d'un objet différent et la question de performance est la réponse de ZeePrime, car BuildUp n'est exécuté que sur FrameworkElements dont vous avez besoin. –