Setter Injection或Ambient Context模式

时间:2012-07-26 12:48:28

标签: c# .net design-patterns dependency-injection

我有一些全局组件我不知道如何将它们放入设计中。如:

  • 设置类:它正在连接程序的初始设置,可能是app.config(1way),web.config(1way),硬编码值(1way),或幕后的sqldb(2way)。

  • 语言类:它包含不同的语言集,同样,我可以在它后面有一些resx文件(1way),硬编码值(1way)或sqldb(2way)。 / p>

第一个问题是,我应该在依赖注入中创建这些类的setter属性(我使用Windsor):

public ISettings Settings {set;}
public ILanguage Language {set;}

或者我应该让它们成为环境背景:

string DoSomethingAndReportIt() {
    //do something ...
    var param = Settings.Current.SomeParam;
    //report it ...
    return Language.Current.SomeClass_SomeMethod_Job_Done;
}

我注意到.net库中有一些实际使用环境上下文模式的组件,例如System.Security.Principal,System.Web.ProfileBase,System.Thread.CurrentCulture ...

您认为将我的全局类(如设置和语言)设置为环境上下文类是没有害处的吗?如果没有,为什么DI是首选?与环境相比,它们在单元测试方面是否更有优势?

第二个问题是,如果DI更好,(我觉得DI模式是首选),有什么好的方法来代理现有的环境类,如Security.Principal或Profile,以遵循DI模式?

1 个答案:

答案 0 :(得分:3)

当您需要实现跨多个层的功能时,环境上下文就可以了。 (在您的情况下,您说这两个对象是全局的)此功能称为横切关注点。正如您所注意到的,.NET中的许多类都实现为环境上下文,例如IPrincipal。为了获得环境上下文实现的工作版本,如果将SettingsLanguage对象开发为环境上下文,则需要为其提供一些默认值。我的假设是你将提供ILanguageISettings的一些默认实现,并且考虑到你将在全球范围内使用它们,它们是环境背景的良好候选者。

另一方面,您计划多久使用一次实现这两个接口的对象?并且,两个对象的存在是否至关重要,意味着Settings != nullLanguage != null?如果您真的打算在一个或两个类中使用它们,和/或如果对象的存在不是很重要,您可能希望使用 setter injection 。 setter注入实际上不需要默认值,因此您的对象可以是null

就个人而言,我不是环境背景的粉丝。但是,如果它被证明是最可接受的解决方案,我会使用它。在你的实现的情况下,我会做这样的事情:因为你需要初始化实现两个接口的对象一次只在一个位置,你可以从环境上下文开始。如果您意识到您在极少数位置使用它,请考虑将其重构为setter注入。如果对象的存在很重要,请考虑构造函数注入实现。