IoC 容器通常允许您指定对象的生活方式。例如,SimpleInjector 提供了开箱即用的 Transient 和 Singleton(还允许用户创建自定义生活方式类)。使用 SimpleInjector 很简单:
container.Register<ISvc, Impl>(Lifestyle.Singleton);
或者
container.Register<ISvc, Impl>(Lifestyle.Transient);
无需使用组合逻辑污染您的类。
至于配置原语,一种常见的做法是将它们放在接口后面。例如,我将连接字符串放在 IDatabaseConfiguration 接口后面,它的实现从 web.config 读取值。然后我将该接口注入到我的数据服务中。
编辑:忽略以上。保留它,以便评论有意义。
以下内容实际上并没有回答问题,但它可能会解决提示问题的问题。你说这个类做了一些有用的缓存,这让我知道它正在承担额外的责任。因此,我建议您不要尝试将该单个实现注册为单例,而是围绕该实现创建一个装饰器类。
container.RegisterDecorator(
typeof(ICommandHandler<>),
typeof(CommandHandlerCacheDecorator<>),
Lifestyle.Transient,
x => { return /*some logic that looks for and
finds that one class you want
to decorate*/
});
装饰器需要是一个瞬态的,因为它会对它所装饰的命令有一个瞬态引用。但是,它可以访问一个单独的单例类(当然是通过依赖注入)或处理实际缓存的缓存对象。
编辑:挑出一个类来装饰的例子。有很多选择,具体取决于您想要的具体程度。再次使用 SimpleInjector,但我确信其他容器也有自己的类似物。
//decorate a specific class
x => { return x.ImplementationType.FullName == "My.Commands.Web.SomeName"; }
//decorate all classes that share a certain namespace
x => { return x.ImplementationType.Namespace.EndsWith("Commands.Web"); }
//decorate all classes that implement the same interface
x => { return x.ImplementationType.IsInstanceOfType(typeof(ICouldCache)); }