views:

498

answers:

6

Is there any specific example/instance of DI being applied as an architectural principle or design pattern in the .NET Framework itself? Do any (or many) of the types in the framework/BCL conform to IoC?

The type names and a brief illustration/explanation based in C# would be great!

This would compund the need for DI infused design principle as a best-practice...as it is gleaned from the base framework itself.

I reiterate, I am not looking for IoC/DI Frameworks BUT for IoC/DI IN the framework.

EDIT: Just wanted to get more instances/examples ... hence the bounty!

+11  A: 

Both the StreamReader and StreamWriter could be seen as examples of IoC/DI.

Each allow you to inject a different Stream object (or one of its derivatives) for reading/writing respectively.

FileInfo fi = new FileInfo(@"C:\MyFile.dat");
StreamWriter sw = new StreamWriter(fi.Open());

Or:

MemoryStream ms = new MemoryStream();
StreamWriter sw = new StreamWriter(ms);

Would both allow:

sw.Write("Hello world!");

The same way, no matter what kind of Stream you injected in the call to the constructor.

Justin Niessner
+2  A: 

I am currently reading the book The Art of Unit Testing by Roy Osherove. He mentions a technique called Extract and Overload (that is, injecting a dependency into a class through overriding a virtual method that is responsible for returning the dependency).

I think I've come across various instances of that technique, for example these:

  • Customizing the ADO.NET type DataTable:
    If you derive from DataTable, you have the possibility of overriding various methods, such as GetRowType(), CreateInstance(), and others.

  • Customizing Workflow Foundation Activity designers (in .NET 3.5)
    I don't remember the exact class, but I think if you want to create custom activity designs, you derive new classes from existing ones, and the pattern is much the same; you override a virtual method which allows you to return your custom dependency to the framework.

stakx
+5  A: 

Sure - the IServiceProvider interface has been part of the Framework since 1.0. This isn't DI as it is typically discussed here (using a "kernel"), but it is IoC using the Service Locator pattern.

If you dig into any of the Windows Forms Designer code, you'll see it peppered liberally with lines like this one:

IDesignerOptionService service = 
    (IDesignerOptionService)this.GetService(typeof(IDesignerOptionService));

If you're working with a Component, then you get access to this via the Site property. It's quite common and practically required knowledge when creating custom controls.

This is Service Location, textbook example. You've got a generic IServiceProvider that hands out abstract services you request by service type. If you ever want to create custom designers - smart tags and so on - then you need to know all of this. It's similar for ASP.NET as well.


P.S. Please don't use IServiceProvider in new code. It's a very old, non-generic interface. If you are creating reusable libraries that require an IoC container in order to work, you should use the Common Service Locator instead. But don't even use that unless you absolutely require that your library be agnostic of the DI library used at the application tier; most of the implementation-specific containers/kernels offer much richer APIs that you'll miss out on if you nail yourself to the CSL.

Aaronaught
+4  A: 

This is an example of how you can create a System.ComponentModel.Composition.Hosting.CompositionContainer in .NET 4:

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);

This is an example of dependency injection via constructor arguments. Because the dependency injection pattern was followed, these classes are very extensible: you can write your own ComposablePartCatalog implementation and pass that to the export provider constructor. Or you can bypass the whole concept of part catalogs and write your own ExportProvider implementation.

(Incidentally, CompostionContainer is itself part of an IoC framework, but that's not the point of this example.)

Wim Coenen
+13  A: 

In general there aren't a lot of examples of DI in the BCL - perhaps because the BCL is a rather self-contained framework, and DI is more of an application architecture concern... However, here are some examples I've been able to find so far.

Constructor Injection

There are not many examples of Constructor Injection in the BCL. The best candidates are

  • System.IO.StreamWriter
  • System.IO.StreamReader

Property Injection

  • System.ComponentModel.IComponent.Site

We also see a variation in Workflow Foundation's WorkflowRuntime.AddService and related methods, although you might argue that this is closer to Method Injection.

Method Injection

  • System.ComponentModel.Design.IDesigner.Initialize
  • System.ComponentModel.TypeConverter (many methods take ITypeDescriptorContext)
  • System.Web.Mvc.IModelBinder.BindModel (from ASP.NET MVC)

Ambient Context

  • System.Threading.Thread.CurrentPrincipal
  • System.Threading.Thread.CurrentCulture
  • System.Threading.Thread.CurrentUICulture
  • System.Diagnostics.Trace.Listeners

FWIW, I drew these examples from my upcoming book.

Mark Seemann
I guess I can't really compete with somebody who wrote a book on the subject...I'm just glad I nailed one of the examples from the list. Haha.
Justin Niessner
+3  A: 

.NET, especially in a web context, offers Providers to define alternative implementations of framework components. The framework defines an abstract base class, defines one or two concrete implementations on top of it, and allows users to provide their own implementations where desired.

Once defined, the user doesn't control the life-cycle of their implementation. The framework takes over and manages instantiation, setup, and disposal.

Start with System.Configuration.Provider.ProviderBase.

.NET classes that implement ProviderBase:

  • System.Configuration.ProtectedConfigurationProvider - encrypting and decrypting protected-configuration data
    • System.Configuration.DpapiProtectedConfigurationProvider (concrete)
    • System.Configuration.RsaProtectedConfigurationProvider (concrete)
  • System.Configuration.SettingsProvider - custom settings in the application settings architecture
    • System.Configuration.LocalFileSettingsProvider (concrete)
    • System.Web.Profile.ProfileProvider
      • System.Web.Profile.SqlProfileProvider (concrete)
  • System.Web.Management.WebEventProvider - customize the ASP.NET health-event processing
    • System.Web.Management.BufferedWebEventProvider
      • System.Web.Management.MailWebEventProvider
        • System.Web.Management.SimpleMailWebEventProvider (concrete)
        • System.Web.Management.TemplatedMailWebEventProvider (concrete)
      • System.Web.Management.SqlWebEventProvider (concrete)
    • System.Web.Management.EventLogWebEventProvider (concrete)
    • System.Web.Management.IisTraceWebEventProvider (concrete)
    • System.Web.Management.TraceWebEventProvider (concrete)
    • System.Web.Management.WmiWebEventProvider (concrete)
  • System.Web.Security.MembershipProvider - custom membership for membership services
    • System.Web.Security.ActiveDirectoryMembershipProvider (concrete)
    • System.Web.Security.SqlMembershipProvider (concrete)
  • System.Web.Security.RoleProvider - custom role-management for role-management services
    • System.Web.Security.AuthorizationStoreRoleProvider (concrete)
    • System.Web.Security.SqlRoleProvider (concrete)
    • System.Web.Security.WindowsTokenRoleProvider (concrete)
  • System.Web.SessionState.SessionStateStoreProviderBase - session-state data stores
    • System.Web.SessionState.InProcSessionStateStore (concrete)
    • System.Web.SessionState.OutOfProcSessionStateStore (concrete)
    • System.Web.SessionState.SqlSessionStateStore (concrete)
  • System.Web.SiteMapProvider - custom SiteMap persistent data store
    • System.Web.StaticSiteMapProvider
      • System.Web.XmlSiteMapProvider (concrete)
  • System.Web.UI.WebControls.WebParts.PersonalizationProvider - loads and stores personalization data on behalf of a WebPartPersonalization instance
    • System.Web.UI.WebControls.WebParts.SqlPersonalizationProvider (concrete)

Examples:

Corbin March