Unity 2.0: How to use Resolve with ResolverOverride?

Solution 1:

As you have noticed this is a new (and really cool feature) of the Unity 2. This feature let you

  • pass parameters to constructor in the moment when you resolve the class. In unity 1 you can set only one value in the moment when you register type via new InjectionConstructor(...)

There is ParameterOverride : ResolverOverride

A ResolverOverride class that lets you override a named parameter passed to a constructor.

  • same for dependencies with DependencyOverride : ResolverOverride

A class that overrides the value injected whenever there is a dependency of the given type, regardless of where it appears in the object graph.

  • same for properties with PropertyOverride : ResolverOverride

A ResolverOverride that lets you override the value for a specified property.

Example

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; }

    }
}

Have no idea why does Google keeps silent about that.

Quotes are from Unity source code xml docs.

Solution 2:

Just in case someone is interested, I have made an extension method that makes the syntax for resolving using ParameterOverride a little easier to read. The method is as follows:

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 :)
    }
}

With this, you can rewrite the ParameterOverride example as follows:

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

I hope this is useful for someone...

Solution 3:

Just to add my 2c. You can just add a ParameterOverrides like so:

Container.Resolve<IConcreteService>(new ParameterOverrides
{                                                                                   
  {"val", 42}
});