Unity 2.0:如何在ResolverOverride中使用Resolve?


68

我开始与Unity进行越来越多的工作。我注意到Resolver方法采用了params参数ResolverOverride

有人可以给我一个例子,说明我如何使用ResolverOverride或为我提供一些其他信息,以获取更多线索。

Answers:


111

如您所知,这是Unity 2的一项新功能(非常酷)。

  • 在解析类时将参数传递给构造函数。在unity 1中,通过新的InjectionConstructor(...)注册类型时,您只能设置一个值。

ParameterOverride : ResolverOverride

ResolverOverride类,使您可以重写传递给构造函数的命名参数。

  • 与依赖项相同 DependencyOverride : ResolverOverride

一个类,只要有给定类型的依赖项,它就会覆盖注入的值,无论它在对象图中的位置如何。

  • 对于具有相同的属性 PropertyOverride : ResolverOverride

ResolverOverride,使您可以覆盖指定属性的值。

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

    }
}

不知道Google为什么对此保持沉默。

引号来自Unity源代码xml文档。


1
感谢您的答复。+1
Vadim

这是一个很大的帮助。很好解释。
Andrew Anderson

1
对于构造函数注入,它仍然不是很好。重命名构造函数参数时,参数覆盖将中断。理想情况下,解决方法应该采用InjectionConstructor
Frank Q.

46

以防万一有人感兴趣,我做了一个扩展方法,使解析语法使用起来ParameterOverride更容易阅读。方法如下:

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

这样,您可以重写ParameterOverride示例,如下所示:

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

我希望这对某人有用...


此扩展名的问题在于,它也将覆盖公共静态T Resolve <T>(此IUnityContainer容器,字符串名称,参数ResolverOverride []覆盖)扩展方法,因此,如果您尝试按名称解析类型而没有其他参数将失败。只需将扩展名更改为其他名称即可解决问题。:)
Dmitri M

14

只是添加我的2c。您可以像这样添加ParameterOverrides:

Container.Resolve<IConcreteService>(new ParameterOverrides
{                                                                                   
  {"val", 42}
});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.