代码之家  ›  专栏  ›  技术社区  ›  stiank81

典型的IOC容器使用-将数据向下传递

  •  4
  • stiank81  · 技术社区  · 15 年前

    我最近开始使用 IoC 容器是第一次,但我没有受过使用它的最佳实践的教育。更详细地说,我正在使用 Unity 在C.NET项目中,我开始使用它,因为它附带了 Prism .

    我使用容器解析“顶级”对象,然后根据容器注入正确的对象。但是,当我有一个对象是儿童和儿童的时候,我看不清楚最佳实践,我需要从IOC容器中一直获取一些数据,但不能在两者之间。您通常如何组织使用IOC容器?

    最初,我认为您将把容器传递到需要它的任何地方,而不是从顶层的容器中提取所需的数据并传递这些数据。但是,当我访问对象时,我再次遇到了一些问题,这些对象除了被注入的接口之外还具有其他特定的数据,我不希望在解析对象之后通过属性或init方法注入这些数据。

    我希望这足够清楚,但是让我们来看一个虚构的(稍微愚蠢的)例子。

    class Employee
    {
        private ICommands _commands; 
        priate List<Customer> _customers = new List<Customer>(); 
        public Employee(ICommands commands)
        {
            _commands = commands; 
        }
        public void AddCustomer(string customerName)
        {
            var customer = new Customer(customerName, _commands); 
            _customers.Add(customer); 
        }
    }
    
    class Customer 
    {
        private string _name; 
        private ICommands _commands; 
        priate List<Case> _cases = new List<Case>(); 
        public Customer(string, name, ICommands commands)
        {
            _name = name; 
            _commands = commands; 
        }
        public void AddCase()
        {
            var case = new Case(_commands); 
            _cases.Add(case); 
        }
    }
    
    class Case    {
        private ICommands _commands; 
        public Customer(ICommands commands)
        {
            _commands = commands; 
        }
        public void TriggerCommands()
        {
            _command.TriggerSomething(); 
        }
    }
    

    所以,这个例子并没有多大意义,但本质上和我需要做的是一样的。我有一些应用程序命令通过我的viewModel类传递,因为其中一些命令需要能够触发命令来显示某些内容。我也有公共存储空间等,这可能是某些类所需要的,但目前是通过和存储在中间类中的。如果只使用命令,那么存储命令或容器就没什么大不了的,但是在典型的IOC使用中,是否会有一个将IOC容器传递给另一个,并将其用于解析行中的对象?像客户名称这样的具体数据呢?你不能只在resolve()上传递这个,所以你需要在之后注入它?

    对不起-这是我能做到的最短的。不需要相同长度的答案;-)。只是;用IOC容器做这种事情的最佳实践是什么?

    4 回复  |  直到 12 年前
        1
  •  3
  •   Peter Mortensen icecrime    14 年前

    我不太确定我理解你的问题。但我认为你根本不应该把集装箱放在附近。只为容器创建包装类要容易得多。例如:

    public class IoCContainer
    {
      private static ContainerType = null;
    
      public static ContainerType Instance 
      {
        get 
        {
          if (_container == null)
          {
            string configFileName = ConfigurationManager.AppSettings[ConfigFileAppSettingName];
            _container = new WindsorContainer(new XmlInterpreter(configFileName));
          }
    
          return _container;
        }
      }
    }
    

    现在您可以在代码中的任何地方调用它。

    IoCContainer.Instance.Resolve<IAwesomeService>(); 
    

    这对你有帮助吗?

        2
  •  2
  •   Konamiman    15 年前

    我不确定这是否回答了您的问题,但我想说,使用Unity容器(我认为也适用于其他IOC引擎)处理应用程序的一个好方法是:

    • 设计你的课程,使所有 指定了必需的依赖项 在构造函数中。这样你 不需要明确处理 团结,除非你需要创造新的 物体。
    • 如果需要创建新对象 在你的班级里,通过团结 构造函数中的容器本身 以及(作为对 IUnityContainer )并创建所有新的 通过使用 Resolve 方法。即使是对于那些没有 已注册且没有依赖关系, 容器会给你一个合适的 实例,稍后您可以决定注册以前未注册的类型,而不更改客户端代码。
    • 对于向解析对象传递显式值,可以在注册类型时指定具体的注入成员(请参见 InjectionMembers 中的参数 RegisterType 班级)。
        3
  •  1
  •   Community CDub    8 年前

    似乎你需要为你的实体申报工厂。通过构造函数注入解析工厂,并通过创建方法传递数据值。所有其他依赖项必须通过工厂的构造函数来解决。

    this 回答。

        4
  •  0
  •   liggett78    15 年前

    我将定义一个静态类IOC,它可以用一个特定的容器初始化,并实现诸如resolve、resolve(…)之类的方法,然后将实际工作委托给容器实例(您将把这个实例存储在一个字段或属性中)。这样你就不需要传递任何东西,只需使用

    IoC.Resolve<SomeType>();
    

    代码中的任何地方。

    关于特定的数据:一些容器将接受一个参数并根据这个参数进行解析(autofac有这种特性)。或者,您可以始终创建一个工厂类,该类具有一个接受一组参数(如客户名称)并返回相应对象实例的方法。