【问题标题】:Unity 2.0: How to use Resolve with ResolverOverride?Unity 2.0:如何使用 Resolve 和 ResolverOverride?
【发布时间】:2010-05-11 18:19:57
【问题描述】:

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

谁能给我一个如何使用 ResolverOverride 的例子,或者指出我可以得到更多线索的其他来源。

【问题讨论】:

    标签: .net unity2.0


    【解决方案1】:

    正如您所注意到的,这是 Unity 2 的一个新功能(而且非常酷)。这个功能让您

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

    ParameterOverride : ResolverOverride

    一个 ResolverOverride 类,可让您 覆盖传递给 a 的命名参数 构造函数。

    • 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
    • 这是一个很大的帮助。解释得很好。
    • 对于构造函数注入,它仍然不是很好。重命名构造函数参数时,参数覆盖将中断。理想情况下,resolve 方法应该采用 InjectionConstructor
    【解决方案2】:

    以防万一有人感兴趣,我做了一个扩展方法,使使用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(this IUnityContainer container, string name, params ResolverOverride[] overrides) 扩展方法,所以如果你正在尝试按名称解析类型而不使用其他参数,它将失败。但是,只需将扩展名更改为其他名称即可解决问题。 :)
    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-31
      • 2018-01-16
      相关资源
      最近更新 更多