1

我已经阅读了很多关于 IoC 容器的主题,尤其是 Mark Seemann 的博客文章,其中他强调了约定优于配置的重要性。我理解并同意他的观点,但我想知道如何最好地为不规则的一生划出一个班级?

例如,我的大多数服务都注册了一个Transient生命周期——但我希望将一个特定的服务注册为一个Singleton,因为它做了一些有用的缓存。

我曾考虑过使用一些自定义属性,但我已经阅读了反对这一点的论据(因为它将组合逻辑放在类中)。

例如,对于配置原语的依赖,我也有过同样的争论。最终我最终使用了参数属性,因为它适用于我的情况,但我觉得也许我没有看到“隐藏的危险”。

4

1 回答 1

2

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)); }
于 2013-11-12T17:31:33.203 回答