Alex Hoffman

Perspective on development, management and technology

Syndication

News

    Subscribe

    IASA Member

System.ComponentModel

With much of the Java and OO world discussing Inversion of Control (IoC) patterns, also dubbed "dependency injection" by Martin Fowler, its worth remembering that the .NET Framework has always included a "service locator" pattern which allows a component to access shared "services".

It can be used to support a pattern which provides a mechanism by which one can loosely-couple components - i.e. eliminate hard coded dependencies between objects.  [For those lightweight container aficionados here, .NET's implementation provides for Type 1 (interface) IoC injection of a "Service Locator" into each .NET Component]

It's widely used in the Framework and in tools like Microsoft Visual Studio.  For example, it underpins the Windows Forms Designer architecture, and it is the mechanism through which Windows Forms Controls inherit aspects of the underlying Form.  You could use it to share say a particular ToolBar across Forms, but it goes much further than that - really to the heart of OO and how one can wire together objects without introducing hard-wired dependencies.




One can write loosely-coupled code like that shown below, which "injects" a particular implementation (in this case "SlowDriver") into "myCar".

using System.ComponentModel;

Container myContainer = new Container();
myContainer.Add(
new FastDriver(), "fast");
myContainer.Add(new SlowDriver(), "slow");

IDriver driver = (IDriver)myContainer.Components["slow"];
// error checking removed for brevity

Car myCar = new Car(driver);
Console.WriteLine("Maximum speed is " + myCar.Speed);


Where is it?  It's defined in the System.ComponentModel namespace.  Like the Spring.NET framework, one could use System.ComponentModel to create a context-based pluggable architecture as an alternative to the .NET 2.0 Provider Model.

Unfortunately though, is neither widely known or used, despite the recent big interest in lightweight containers, largely because many interfaces in the namespace don't have default implementations, and because IoC concepts require a good understanding of underlying OO concepts.

The whole area is important for the future because such patterns allow for the separation of configuration from use, something that is really important in terms of Microsoft's future MDA through tools architectural strategy.

Published Thursday, November 25, 2004 4:22 PM by Alex Hoffman

Filed under:

Comments

# re: System.ComponentModel@ Thursday, November 25, 2004 7:41 AM

Daniel Cazzulino wrote similar stuff here: http://weblogs.asp.net/cazzu/archive/2004/05/10/129140.aspx

JosephCooney

# re: System.ComponentModel@ Thursday, November 25, 2004 11:28 AM

In addition to Cazzu's article ( good read) ther is also an implemenation of Constructor Injection Ioc pattern called StructureMap @ http://sourceforge.net/projects/structuremap

Also, here is a little bit extended derived from the sample in this post, for playing around:

using System;
using System.ComponentModel;

namespace TestIoC
{
class ClassMain {
// error checking removed for brevity
static void Main(string[] args) {
Container _container = new Container();

Driver _driver = new FastDriver("bob");
_container.Add(_driver, _driver.Name);

_driver = new SlowDriver("jim");
_container.Add(_driver, _driver.Name);

_driver = new SlowDriver("al");
_container.Add(_driver, _driver.Name);

//--
//...
//--

IDriver _iDriver = (IDriver) _container.Components["bob"];
Car _car = new Car(_iDriver);
Console.WriteLine("{0} maximum speed is {1}", _iDriver.Name, _car.Speed);

_iDriver = (IDriver) _container.Components["jim"];
_car = new Car(_iDriver);
Console.WriteLine("{0} maximum speed is {1}", _iDriver.Name, _car.Speed);

_iDriver = (IDriver) _container.Components["al"];
_car = new Car(_iDriver);
Console.WriteLine("{0} maximum speed is {1}", _iDriver.Name, _car.Speed);

Console.WriteLine("Press ENTER to exit");
Console.ReadLine();
}
}

//--------------------------------------------------------------
class Car {
private IDriver driver;
public int Speed;

public Car(IDriver pDriver) {
driver = pDriver;
Speed = driver.SpeedLimit;
}
}

interface IDriver {
string Name { get; }
int SpeedLimit { get; }
}

abstract class Driver : Component, IDriver {
private string name;
public string Name { get { return name; } }

public Driver(string pName) {
name = pName;
}

abstract public int SpeedLimit { get; }
}

class FastDriver : Driver {
public override int SpeedLimit { get { return 300; } }

public FastDriver(string pName) : base(pName) { }
}

class SlowDriver : Driver {
public override int SpeedLimit { get { return 30; } }

public SlowDriver(string pName) : base(pName) { }
}
}

Srdjan

# Is this the end of Apache Avalon...@ Monday, December 27, 2004 2:38 AM

TrackBack