我有一些全局组件我不知道如何将它们放入设计中。如:
设置类:它正在连接程序的初始设置,可能是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模式?
答案 0 :(得分:3)
当您需要实现跨多个层的功能时,环境上下文就可以了。 (在您的情况下,您说这两个对象是全局的)此功能称为横切关注点。正如您所注意到的,.NET中的许多类都实现为环境上下文,例如IPrincipal
。为了获得环境上下文实现的工作版本,如果将Settings
和Language
对象开发为环境上下文,则需要为其提供一些默认值。我的假设是你将提供ILanguage
和ISettings
的一些默认实现,并且考虑到你将在全球范围内使用它们,它们是环境背景的良好候选者。
另一方面,您计划多久使用一次实现这两个接口的对象?并且,两个对象的存在是否至关重要,意味着Settings != null
和Language != null
?如果您真的打算在一个或两个类中使用它们,和/或如果对象的存在不是很重要,您可能希望使用 setter injection 。 setter注入实际上不需要默认值,因此您的对象可以是null
。
就个人而言,我不是环境背景的粉丝。但是,如果它被证明是最可接受的解决方案,我会使用它。在你的实现的情况下,我会做这样的事情:因为你需要初始化实现两个接口的对象一次只在一个位置,你可以从环境上下文开始。如果您意识到您在极少数位置使用它,请考虑将其重构为setter注入。如果对象的存在很重要,请考虑构造函数注入实现。