注入/解析几乎是单例的对象
本文关键字:单例 对象 注入 | 更新日期: 2023-09-27 17:51:16
背景
我在WPF申请中使用温莎城堡作为我的IOC容器。在该应用程序中,用户可以打开单个项目文件,该文件使用IProjectModel
接口的具体版本进行建模。因此,在任何给定时间,都有零个或一个IProjectModel
实例可用。我目前正在将其实现者的生活方式定义为transient,并且该实现者希望在其构造函数中有一个文件名为string
,由用户(从对话框中(选择。IProjectModel
实例通过类型化的工厂接口解析,例如:
public interface IProjectModelFactory
{
IProjectModel Create(string fileName);
}
问题
我最初认为把它当作一个单例是不好的,因为:
- 它相对于应用寿命是瞬态的
- 它有自己的依赖项,即要打开的文件名(
string
(,如果它有singleton/scoped的生活方式,我想我无法指定 - 传递它可以同时打开多个项目
然而,现在我正在创建一个又一个工厂,以便通过当前的IProjectModel
实例,我有点后悔这个决定。让容器将当前项目模型交给我的对象会容易得多,而不是从对象链的上游传递它。
使用温莎城堡应该如何处理这种情况
Scoped Lifestyle似乎是为此而构建的(范围是当前打开的项目/文件名(,但我不知道如何将打开的文件的信息输入到IScopeAccessor
中,因为我无法向其中注入任何内容。
IProjectModel听起来像是包含数据——也就是说,它不是一个纯粹的服务。
考虑对它进行建模,就像对由数据库支持的服务进行建模一样,但不要连接到数据库,而是使用一些内存中的构造。它可能和服务实现中的静态成员变量一样简单。类似于:
public class ProjectDataService : IProjectDataService
{
private static IProjectModel _projectModel;
public IProjectModel Create(string fileName)
{
if (_projectModel == null)
{
//create it
}
return _projectModel;
}
}
(请注意,您可能需要对成员变量进行一些锁定。(
现在,如果您需要切换到同时打开多个项目,请将您的成员变量更改为列表结构(IList、Dictionary等(
根据您的评论进行编辑。
我指的是一旦它已经创建。IOC背后的大想法似乎是"让容器处理依赖关系",温莎似乎可以支持这一点,我只是不知道如何支持。我想在瞬态对象的构造函数中指定IProjectModel,并让容器解析当前的IProjectModel(如果有的话(。你的答案是懒惰的单身汉,这不是我想要的
我想说的是IProjectModel并不是一个真正的服务——它是状态/数据。所以直接注射是没有意义的(至少对我来说没有意义(。将其封装在IProjectModel数据服务或IProjectModel"状态管理器"中更符合注入服务,这是DI框架通常所做的
你能注册IProjectModel吗?对但是,容器注册通常在应用程序引导时进行,而不是基于用户输入。此外,根据您的描述,您可能需要支持IProjectModel的多个实例。当你请求时,容器如何知道该给你哪个实例?
举个更明显的例子:你会考虑在构造函数中注入字符串或int吗?
让容器处理依赖项并不是我所说的IOC背后的"大创意"。这是关于与服务依赖性解耦(或处理(。因此,如果您想注入有状态的东西,我建议您将该状态封装在一个可以像服务一样注入的类中。