注入/解析几乎是单身的对象

时间:2014-03-20 21:01:38

标签: c# dependency-injection inversion-of-control castle-windsor ioc-container

背景

我在使用Castle Windsor作为WPF应用程序中的IOC容器。在此应用程序中,用户可以打开单个项目文件,该文件使用IProjectModel接口的具体版本建模。因此,在任何给定时间,可以使用IProjectModel个零个或一个实例。我目前正在将其实现者的生活方式定义为 transient ,并且此实现者在其构造函数中期望文件名为string,由用户选择(来自对话框)。 IProjectModel实例通过typed factory interface解析,例如:

public interface IProjectModelFactory
{
    IProjectModel Create(string fileName);
}

问题

我最初认为将它作为单身人士处理是不好的:

  1. 在应用程序生命周期方面是暂时的;
  2. 它有自己的依赖关系,即文件名(string)要打开,我不认为我可以指定它是否有单身/范围的生活方式;
  3. 传递它会保持打开一次打开多个项目的选项。
  4. 然而,现在我为了传递当前的IProjectModel实例而在工厂之后创建工厂,我对这个决定感到有些遗憾。容器将我的对象当作项目模型更容易,而不是从对象链向上传递它。

    如何使用Castle Windsor处理这样的情况?

    似乎Scoped Lifestyle是为此构建的(范围是当前打开的项目/文件名),但我无法弄清楚如何将打开的文件的信息输入{{ 3}}因为我无法注入任何东西。

1 个答案:

答案 0 :(得分:2)

IProjectModel听起来像包含数据 - 即。这不是一项纯粹的服务。

考虑对它进行建模,就像建模由数据库支持的服务一样,但不是连接到数据库,而是使用一些内存中构造。它可能与服务实现上的静态成员变量一样简单。类似的东西:

public class ProjectDataService : IProjectDataService
{
    private static IProjectModel _projectModel;

    public IProjectModel Create(string fileName)
    {
        if (_projectModel == null)
        {
            //create it
        }
        return _projectModel;
      }
 }

(请注意,您可能需要对成员变量进行一些锁定。)

现在,如果您需要切换到同时打开多个项目,请将您的成员变量更改为列表结构(IList,Dictionary等)。


根据您的评论进行修改。

我指的是它已经被创建了。 IOC背后的重要思想似乎是“让容器处理依赖关系”,似乎Windsor可以支持这一点,我只是不知道如何。我想在瞬态对象的构造函数中指定IProjectModel,并让容器解析当前的IProjectModel(如果有的话)。你的答案是一个懒惰的单身人士,这不是我要求的。

我所说的是IProjectModel并不是真正的服务 - 它是状态/数据。因此直接注入它是没有意义的(至少对我而言)。将它包装在IProjectModel数据服务或IProjectModel“状态管理器”中更符合注入服务,这正是DI框架通常所做的。

你可以注册一个IProjectModel吗?是。但是,容器注册通常在应用程序引导时完成,而不是基于用户输入。此外,根据您的描述,您可能需要支持IProjectModel的多个实例。当你要求时,容器如何知道给你的实例?

作为一个更明显的例子:你会考虑在构造函数中注入一个字符串或一个int吗?

让容器处理依赖并不完全是我如何描述IOC背后的“大创意”。它是关于(或处理)服务依赖性的解耦。因此,如果你想注入一些有状态的东西,我建议你将这个状态包装在一个可以像服务一样注入的类中。