Unity 2.0: Wie verwende ich Resolve mit ResolverOverride?

68

Ich begann immer mehr mit Unity zu arbeiten . Ich stelle fest, dass die Resolver-Methode ein params- Argument ResolverOverride verwendet .

Kann mir jemand ein Beispiel geben, wie ich ResolverOverride verwenden kann, oder mir eine andere Quelle zeigen, wo ich weitere Hinweise erhalten kann.

Vadim
quelle

Antworten:

111

Wie Sie bemerkt haben, ist dies eine neue (und wirklich coole) Funktion von Unity 2. Mit dieser Funktion können Sie

  • Übergeben Sie die Parameter in dem Moment an den Konstruktor, in dem Sie die Klasse auflösen. In Einheit 1 können Sie in dem Moment, in dem Sie den Typ über den neuen InjectionConstructor registrieren (...), nur einen Wert festlegen.

Es gibt ParameterOverride : ResolverOverride

Eine ResolverOverride-Klasse, mit der Sie einen benannten Parameter überschreiben können, der an einen Konstruktor übergeben wird.

  • Gleiches gilt für Abhängigkeiten mit DependencyOverride : ResolverOverride

Eine Klasse, die den injizierten Wert überschreibt, wenn eine Abhängigkeit des angegebenen Typs besteht, unabhängig davon, wo sie im Objektdiagramm angezeigt wird.

  • Gleiches gilt für Immobilien mit PropertyOverride : ResolverOverride

Ein ResolverOverride, mit dem Sie den Wert für eine angegebene Eigenschaft überschreiben können.

Beispiel

using System;
using Microsoft.Practices.Unity;

namespace ConsoleApplication1 {
    class Program {
        static void Main(string[] args) {

            var container = new UnityContainer();

            //ParameterOverride example

            container.RegisterType<IConcreteService, ConcreteService>(
                new InjectionConstructor(7) //Old way to pass value to constructor - not flexible. 
                                            //All resolved (without override which appears only in unity 2.0) classes will have val=7
                );

            var service0 = container.Resolve<IConcreteService>();
            Console.WriteLine(service0.Val); //prints 7

            var service = container.Resolve<IConcreteService>(new ParameterOverride("val", 3));
            Console.WriteLine(service.Val); // prints 3

            var service2 = container.Resolve<IConcreteService>(new ParameterOverride("val", 5));
            Console.WriteLine(service2.Val); // prints 5

            Console.ReadLine();

            //DependencyOverride example

            var b0 = container.Resolve<B>(new DependencyOverride<IConcreteService>(new ConcreteService(42)));
            Console.WriteLine(b0.Service.Val); //print 42
            Console.WriteLine(b0.Service1.Val); //print 42

            var b = container.Resolve<B>(new DependencyOverride<IConcreteService>(new ConcreteService(-42)));
            Console.WriteLine(b.Service.Val); // print -42
            Console.WriteLine(b.Service1.Val); // print -42

            Console.ReadLine();

            //PropertyOverride example 

            var b1 = container.Resolve<B>(new PropertyOverride("Service", new ConcreteService(42)), 
                new PropertyOverride("Service1", new ConcreteService(-42)));
            Console.WriteLine(b1.Service.Val); //print 42
            Console.WriteLine(b1.Service1.Val); //print -42

            Console.ReadLine();



        }
    }

    public interface IConcreteService {
        int Val { get; set; }
    }
    public class ConcreteService : IConcreteService {

        public int Val { get; set; }

        public ConcreteService(int val) {
            Val = val;
        }
    }

    public class B {
        [Dependency]
        public IConcreteService Service{ get; set; }

        [Dependency]
        public IConcreteService Service1 { get; set; }

    }
}

Ich habe keine Ahnung, warum Google darüber schweigt.

Zitate stammen aus XML-Dokumenten des Unity-Quellcodes.

er-v
quelle
1
Danke für eine tolle Antwort. +1
Vadim
Das war eine große Hilfe. Sehr gut erklärt.
Andrew Anderson
1
Für die Konstruktorinjektion ist es immer noch nicht großartig. Die Parameterüberschreibung wird unterbrochen, sobald Sie den Konstruktorparameter umbenennen. Idealerweise sollte die Auflösungsmethode InjectionConstructor
Frank Q.
46

Nur für den Fall, dass jemand interessiert ist, habe ich eine Erweiterungsmethode entwickelt, die die Syntax für das Auflösen mit ParameterOverrideetwas einfacher zu lesen macht. Die Methode ist wie folgt:

public static class UnityExtensions
{
    public static T Resolve<T>(this IUnityContainer container, object parameterOverrides)
    {
        var properties = parameterOverrides
            .GetType()
            .GetProperties(BindingFlags.Public | BindingFlags.Instance);
        var overridesArray = properties
            .Select(p => new ParameterOverride(p.Name, p.GetValue(parameterOverrides, null)))
            .Cast<ResolverOverride>()
            .ToArray();
        return container.Resolve<T>(null, overridesArray); //null needed to avoid a StackOverflow :)
    }
}

Damit können Sie das ParameterOverride-Beispiel wie folgt umschreiben:

var service = container.Resolve<IConcreteService>(new {val=3});

Ich hoffe das ist nützlich für jemanden ...

Konamiman
quelle
Das Problem mit dieser Erweiterung besteht darin, dass sie auch die öffentliche statische T Resolve <T> -Erweiterungsmethode (dieser IUnityContainer-Container, Zeichenfolgenname, Parameter ResolverOverride [] überschreibt) überschreibt. Wenn Sie also versuchen, einen Typ nach Namen mit der Nummer aufzulösen zusätzliche Parameter wird es fehlschlagen. Sie müssen jedoch nur den Namen der Erweiterung in etwas anderes ändern und das Problem lösen. :)
Dmitri M
14

Nur um meine 2c hinzuzufügen. Sie können einfach einen ParameterOverrides wie folgt hinzufügen:

Container.Resolve<IConcreteService>(new ParameterOverrides
{                                                                                   
  {"val", 42}
});
Ciaran O'Neill
quelle