典型的IoC容器使用 - 沿线传递数据

时间:2009-10-23 10:53:16

标签: c# .net unity-container ioc-container

我最近第一次开始使用IoC容器,但我没有接受过使用它的最佳实践的教育。更具体地说,我在C#.NET项目中使用Unity,我开始使用它,因为它带有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 个答案:

答案 0 :(得分:3)

我不太清楚我理解你的问题。但我认为你根本不应该把容器转过来。为容器创建一个包装类要容易得多。例如:

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>(); 

这对你有帮助吗?

答案 1 :(得分:2)

我不确定这是否能回答您的问题,但我想说使用Unity容器(也适用于我认为的其他IoC引擎)对应用程序采取行动的好方法是:

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

答案 2 :(得分:1)

您似乎需要为实体声明工厂。通过构造函数注入解析工厂并通过Create方法传递数据值。必须通过工厂的构造函数解析所有其他依赖项。

请参阅this回答。

答案 3 :(得分:0)

我定义了一个静态类IoC,可以使用特定容器进行初始化,并实现Resolve,Resolve(...)等方法,然后将实际工作委托给容器实例(你将存储它)在一个领域或财产中的实例)。这样你就不必传递任何东西,只需使用

即可
IoC.Resolve<SomeType>();

代码中的任何位置。

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