March 2005 - Posts

After quite a struggle I finally got the GotDotNet workspace for Enterprise Library Configuration Console extensions working!

I am currently developing an Xml editor that runs from within the configuration console. The goal is to allow the configuration of any type of xml document, without having to write ConfigurationNode classes. More about this as soon as it has reached its first beta version.

I also added my two other EntLib configuration console extensions to the goodies list, at the bottom left corner of my weblog.

These are:

·         ConfigConstsWriter: Useful configuration node to validate the configuration node names you use at compile-time.

·         ConfigDesignerVerbs: A framework(-ish) set of assemblies that enables developers to create DesignerVerbs for their configuration nodes.

There’s an example that works with the ‘Sql connection string’- node & checks the connectionstring against a running instance of Sql-server.

Recently I’ve become pretty enthusiastic about a phenomenon called “Inversion of Control”- or IoC- containers. The hype is blowing over from the J2EE community and is making its way into the .NET community pretty rapidly. IOC could also go by the more imaginative name “plug-in architecture” and is the essence of the .NET ComponentModel implementation.

 

If the term “Inversion of Control” doesn’t ring a bell and you’re dying to know more, Fowler does a good job explaining it over here.

 

If you already do know IoC or the ComponentModel, you might get cheated on in this article. I’m doing my best to prove a single point at a time. Trying to explain ‘the whole lot’ in a single sentence (as I usually try to) more than once resulted in puzzled listeners.

 

 

 

One of the main things IoC does is fixing a common OO problem that occurs when a class encapsulates (or inherits from) another class and also has to deal with its dependencies. Please consider the following code snippet that could be part of a LoginComponent:

private ResourceManager _resourceManager;

private EventLogger _eventLogger;
/* ..other encapsulations.. */


public LoginComponent()

{

       _resourceManager = new ResourceManager();

       _eventLogger = new EventLogger();

 

       //initialisation of encapsulated objects

}

public void DoLogin(string username, string password)

{

       //

       // login code

       //

 

       if (loginUnsuccessfull)

       {

              string logMessage = _resourceManager.GetString("LOGON_UNSUCCESSFUL_MSG");

              _ eventLogger.WriteLogEntry(string.Format(logMessage, username));

       }

}

 

Even though the login code above might be something you wrote plenty of times as a software developer, the possibility of reusing the code is limited.

 

For the sake of meeting a particular project requirement (the logging of unsuccessful login attempts) the component relies on an implementation of “ResourceManager” and “EventLogger”. The technology used for logging might be your personal favorite (is it Log4NET? EntLib? EIF?) but whichever technology you use, it might conflict with requirements on your next project.

 

 

 

Before I make the obvious comparison to the Factory pattern, I would like to start with showing code using a (IoC-) container. The “Container” class used is a know-it-all factory that serves instances based on configuration settings.

 

public class DefaultLoginFunctionality: ILoginFunctionality
 

private ITinyTextFunctionality _resourceManager;

private ILogWriterFunctionality _errorLogger;

 

public DefaultLoginFunctionality()

{

       _resourceManager = (ITinyTextFunctionality) Container.ServeInstance("TinyTextReader");

       _errorLogger = (ILogWriterFunctionality) Container.ServeInstance("LogWriter");

}

 

 

public void DoLogin(string username, string password)

{

       //

       // login code

       //

 

       if (loginUnsuccessfull && _resourceManager != null && _errorLogger != null)

       {

              string logMessage = _resourceManager.GetString("LOGON_UNSUCCESSFUL_MSG");

              _errorLogger.WriteLogEntry(string.Format(logMessage, username));

       }

}

 

 

Looking at the code above you should have noticed the following changes:

1.)   The names of the “_resourceManager” and “_errorLogger” changed into more functional onces.

2.)   The classes became interface definitions.

3.)   Initialization of the dependencies is gone.

4.)   The code stopped assuming a “_resourceManager” or “_errorLogger” is present and acts accordingly.


The dependency changed from technology to functionality. The functionality is given form by whatever the instance the Container serves.

 

The Container serves instances specified in configuration. Configuration can be defined per environment (thus per project) and project requirements are met accordingly. The code is therefore reusable in different environments.

 

The initialization of the served instances is done prior to serving them. Every implementation that can be served by the Container has the ability to initialize itself prior to being served. This initialization is done from configuration private to the served implementation.

 

 

 

Compared to the ‘Factory pattern’ (or AbstractFactory) I think IoC is superior, but I must admit the differences aren’t all that big.

 

First and foremost, factory patterns use a typed factory and abstact baseclass in their definitions. Every factory is written to serve a specific baseclass and because of this writing a single factory is way more intensive that writing an interface definition.

 

The trend for factory patterns is that the implementations they serve are bigger and the variety of implementations is less. Within a Container you can easily setup an interface definition that only has a method or two. Using a factory this usually would be too much of a hassle. Would you write a factory & baseclass to serve resource strings?

 

Besides this main point, when deriving from an abstract baseclass you’re wrecking your implementations inheritance chain. Abstract baseclasses can contain bugs (interfaces cannot). And IoC has a really clear view on context and sharing implementation amongs each other, this is done less with factory implementations.

 

 

 

I’d like to wrap up with having a quick look at the ComponentModel in .net. 

The ComponentModel has shown us that different development environments (Borland’s Delphi for .NET & C# Builder, ICSharpCode’s #develop) all managed to show us the same set of controls within their designers.

They did this by serving implementations to a set of interfaces similar to the ISelectionService shown below.

And that; I think is pretty amazing!

public interface ISelectionService

{

      // Events

      event EventHandler SelectionChanged;

      event EventHandler SelectionChanging;

 

      // Methods

      bool GetComponentSelected(object component);

      ICollection GetSelectedComponents();

      void SetSelectedComponents(ICollection components);

      void SetSelectedComponents(ICollection components, SelectionTypes selectionType);

 

      // Properties

      object PrimarySelection { get; }

      int SelectionCount { get; }

}

 

 

 

In the next couple of weeks I’ll be posting some articles about IoC on my blog.

Even though  I'm pretty enthousiastic, I'm still finding out 'my way' with IoC. For me this means a lot of experimenting, discussing and nowadays… blogging about it. Because I still haven’t got a clear picture (let's say 90% there) on how IoC is going to help me I’ll split it up in ‘baby steps’. I’ll try to target one aspect a time.

Meanwhile I’m developing an application framework on top of the IoC concept, Hopefully people reading my blog care to give me feedback I can use.

Thanks to Dennis v/d Stelt I got rid of my former weblog on msn spaces and from now on will be blogging here.

I'll be blogging about .NET (and such).