Friday, November 18, 2005

Adding PicoContainer

I recently blogged about Rich Client Development in a 4 part series that led to a small reference implementation. It is immature, but it's in perfect condition to demonstrate the value of PicoContainer.

The current implementation of the EntryPoint class looks like this:
public class EntryPoint
{
[STAThread]
static void Main()
{
MainForm mainForm = new MainForm();
UserData userData = createUser();
new MainPresenter(mainForm, createPresenterFactory(userData));
Application.Run(mainForm);
}

private static UserData createUser()
{
UserData user = new UserData();
user.Name = "John Doe";
user.JobTitle = "Rockstar";
user.PhoneNumber = "212-555-1212";
user.Password = "password";
return user;
}

private static PresenterFactory createPresenterFactory(UserData user)
{
return new PresenterFactory(getPresenters(user));
}

private static IPresenter[] getPresenters(UserData user)
{
return new IPresenter[] { getReadPresenter(user), getUpdatePresenter(user) };
}

private static IPresenter getReadPresenter(UserData user)
{
ReadView view = new ReadView();
return new ReadPresenter(view, user);
}

private static IPresenter getUpdatePresenter(UserData user)
{
UpdateView view = new UpdateView();
return new UpdatePresenter(view, user);
}
}

While this is clean, it's a bit more verbose than necessary. A simpler solution is to register each type with PicoContainer and allow Pico to resolve the dependencies. The only exception is that I would like to populate a UserData instance that will be used as a constructor argument to many other classes. Pico allows me to do this using RegisterComponentInstance. Converting my EntryPoint class to take advantage of PicoContainer causes the implementation to look like this:
public class EntryPoint
{
[STAThread]
static void Main()
{
DefaultPicoContainer container = new DefaultPicoContainer();
container.RegisterComponentInstance(createUser());
container.RegisterComponentImplementation(typeof(PresenterFactory));
container.RegisterComponentImplementation(typeof(MainPresenter));
container.RegisterComponentImplementation(typeof(MainForm));
container.RegisterComponentImplementation(typeof(ReadPresenter));
container.RegisterComponentImplementation(typeof(ReadView));
container.RegisterComponentImplementation(typeof(UpdatePresenter));
container.RegisterComponentImplementation(typeof(UpdateView));
MainPresenter presenter = (MainPresenter) container.GetComponentInstance(typeof(MainPresenter));
Application.Run(presenter.MainForm);
}

private static UserData createUser()
{
UserData user = new UserData();
user.Name = "John Doe";
user.JobTitle = "Rockstar";
user.PhoneNumber = "212-555-1212";
user.Password = "password";
return user;
}
}

This implementation is shorter and arguably easier to understand. Notice PicoContainer creates instance of the dependent objects I need including an array of IPresenters that are used as a constructor argument to the PresenterFactory. If you design your class as Good Citizens and prefer Constructor Injection, adding PicoContainer should be easy and very worthwhile.
Post a Comment