.NET Framework中的控制和dependency injection反转
是否有任何特定的DI示例/实例作为.NET Framework本身的架构原则或设计模式应用? 框架/ BCL中的任何(或许多)类型是否符合IoC?
基于C#的类型名称和简要说明/解释会很棒!
这将使DI注入设计原则成为最佳实践的必要性……因为它是从基础框架本身收集的。
我重申,我不是在为框架中的IoC / DI寻找IoC / DI框架。
编辑:只是想得到更多的实例/例子…因此赏金!
一般来说,BCL中没有很多DI的例子 – 也许是因为BCL是一个相当独立的框架,DI更多的是应用程序架构的关注……但是,这里有一些例子我一直都是能找到目前为止。
构造函数注入
BCL中没有很多构造函数注入的例子。 最好的候选人是
- System.IO.StreamWriter
- 就是System.IO.StreamReader
物业注入
- System.ComponentModel.IComponent.Site
我们还看到了Workflow Foundation的WorkflowRuntime.AddService
和相关方法的变体,尽管您可能会认为这更接近于Method Injection。
方法注入
- System.ComponentModel.Design.IDesigner.Initialize
- System.ComponentModel.TypeConverter(许多方法采用ITypeDescriptorContext)
- System.Web.Mvc.IModelBinder.BindModel(来自ASP.NET MVC)
环境背景
- System.Threading.Thread.CurrentPrincipal
- System.Threading.Thread.CurrentCulture
- System.Threading.Thread.CurrentUICulture
- System.Diagnostics.Trace.Listeners
FWIW,我从即将出版的书中提取了这些例子。
StreamReader和StreamWriter都可以看作是IoC / DI的例子。
每个允许您分别注入不同的Stream对象(或其衍生物之一)进行读/写。
FileInfo fi = new FileInfo(@"C:\MyFile.dat"); StreamWriter sw = new StreamWriter(fi.Open());
要么:
MemoryStream ms = new MemoryStream(); StreamWriter sw = new StreamWriter(ms);
两者都允许:
sw.Write("Hello world!");
同样的方式,无论你在构造函数的调用中注入了什么样的Stream。
当然 – 自1.0以来, IServiceProvider接口一直是Framework的一部分。 这不是DI,因为它通常在这里讨论(使用“内核”),但它是IoC使用服务定位器模式。
如果你深入研究任何Windows窗体设计器代码,你会发现它充满了像这样的行:
IDesignerOptionService service = (IDesignerOptionService)this.GetService(typeof(IDesignerOptionService));
如果您正在使用Component ,那么您可以通过Site属性访问它。 在创建自定义控件时,这是非常常见且实际需要的知识。
这是服务位置,教科书示例。 您有一个通用的IServiceProvider
,可以按服务类型IServiceProvider
您请求的抽象服务。 如果您想创建自定义设计器 – 智能标签等 – 那么您需要了解所有这些。 它与ASP.NET类似。
PS请不要在新代码中使用 IServiceProvider
。 这是一个非常古老的非通用接口。 如果要创建需要IoC容器才能工作的可重用库,则应使用Common Service Locator 。 但是,除非您绝对要求您的库与应用层使用的DI库无关,否则不要使用它 ; 大多数特定于实现的容器/内核提供了更多更丰富的API,如果您将自己定位于CSL,则会错过这些API。
这是一个如何在.NET 4中创建System.ComponentModel.Composition.Hosting.CompositionContainer的示例:
var exeCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly()); var dircatalog = new DirectoryCatalog("."); var aggregateCatalog = new AggregateCatalog(exeCatalog, dirCatalog); var exportProvider = new CatalogExportProvider(aggregateCatalog); var container = new CompositionContainer(exportProvider);
这是通过构造函数参数进行dependency injection的示例。 因为遵循了依赖项注入模式,所以这些类是非常可扩展的:您可以编写自己的ComposablePartCatalog
实现并将其传递给导出提供程序构造函数。 或者您可以绕过零件目录的整个概念并编写自己的ExportProvider
实现。
(顺便提一下, CompostionContainer
本身就是IoC框架的一部分,但这不是这个例子的重点。)
.NET,特别是在Web上下文中,为提供者提供了定义框架组件的替代实现。 该框架定义了一个抽象基类,在其上定义了一个或两个具体实现,并允许用户在需要时提供自己的实现。
一旦定义,用户就无法控制其实现的生命周期。 该框架接管并管理实例化,设置和处置。
从System.Configuration.Provider.ProviderBase开始。
实现ProviderBase的.NET类:
- System.Configuration.ProtectedConfigurationProvider – 加密和解密受保护配置数据
- System.Configuration.DpapiProtectedConfigurationProvider(具体)
- System.Configuration.RsaProtectedConfigurationProvider(具体)
- System.Configuration.SettingsProvider – 应用程序设置体系结构中的自定义设置
- System.Configuration.LocalFileSettingsProvider(具体)
- System.Web.Profile.ProfileProvider
- System.Web.Profile.SqlProfileProvider(具体)
- System.Web.Management.WebEventProvider – 自定义ASP.NET运行状况事件处理
- System.Web.Management.BufferedWebEventProvider
- System.Web.Management.MailWebEventProvider
- System.Web.Management.SimpleMailWebEventProvider(具体)
- System.Web.Management.TemplatedMailWebEventProvider(具体)
- System.Web.Management.SqlWebEventProvider(具体)
- System.Web.Management.MailWebEventProvider
- System.Web.Management.EventLogWebEventProvider(具体)
- System.Web.Management.IisTraceWebEventProvider(具体)
- System.Web.Management.TraceWebEventProvider(具体)
- System.Web.Management.WmiWebEventProvider(具体)
- System.Web.Management.BufferedWebEventProvider
- System.Web.Security.MembershipProvider – 成员资格服务的自定义成员资格
- System.Web.Security.ActiveDirectoryMembershipProvider(具体)
- System.Web.Security.SqlMembershipProvider(具体)
- System.Web.Security.RoleProvider – 角色管理服务的自定义角色管理
- System.Web.Security.AuthorizationStoreRoleProvider(具体)
- System.Web.Security.SqlRoleProvider(具体)
- System.Web.Security.WindowsTokenRoleProvider(具体)
- System.Web.SessionState.SessionStateStoreProviderBase – 会话状态数据存储
- System.Web.SessionState.InProcSessionStateStore(具体)
- System.Web.SessionState.OutOfProcSessionStateStore(具体)
- System.Web.SessionState.SqlSessionStateStore(具体)
- System.Web.SiteMapProvider – 自定义SiteMap持久数据存储
- System.Web.StaticSiteMapProvider
- System.Web.XmlSiteMapProvider(具体)
- System.Web.StaticSiteMapProvider
- System.Web.UI.WebControls.WebParts.PersonalizationProvider – 代表WebPartPersonalization实例加载和存储个性化数据
- System.Web.UI.WebControls.WebParts.SqlPersonalizationProvider(具体)
例子:
- 实施配置文件提供程序
- 实施会员提供者
我目前正在阅读Roy Osherove撰写的The Unit of Unit Testing一书。 他提到了一种名为Extract and Overload的技术(即通过覆盖负责返回依赖关系的虚方法将dependency injection类中)。
我想我遇到过这种技术的各种实例,例如:
-
自定义ADO.NET类型
DataTable
:
如果从DataTable
派生,则可以覆盖各种方法,例如GetRowType()
,CreateInstance()
等。 -
自定义Workflow Foundation活动设计器(在.NET 3.5中)
我不记得确切的类,但我认为如果你想创建自定义活动设计,你可以从现有的类派生新类,并且模式大致相同; 您重写一个虚拟方法,它允许您将自定义依赖项返回到框架。