.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.EventLogWebEventProvider(具体)
    • System.Web.Management.IisTraceWebEventProvider(具体)
    • System.Web.Management.TraceWebEventProvider(具体)
    • System.Web.Management.WmiWebEventProvider(具体)
  • 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.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中)
    我不记得确切的类,但我认为如果你想创建自定义活动设计,你可以从现有的类派生新类,并且模式大致相同; 您重写一个虚拟方法,它允许您将自定义依赖项返回到框架。