Development Blog

 Sunday, November 18, 2007

I haven't posted in a while and decided to write a post about one of the little side projects I've worked on recently. I've been lurking around on the ALT.NET mailing list and one of the discussions I take time to keep up on is on Dependency Injection. Something I worked on a few weeks ago has some applications in that area and so I decided to see what others thought.

I was talking with Aaron several months ago about how many problems constructors in static languages cause. Ruby people are fortunate in that their constructors are much more flexible than their C# counterparts. Want something to be a singleton? Just return the same instance from the constructor! Lifecycle management and dependencies can be the responsibility of the constructor itself, rather than a function of a container.

Over the weekend a few weeks ago I wrote a library and MsBuild task that factors constructor calls out of code and into a pluggable factory system. You write code like this:

public class EmailSender
{
  public void TellEveryone(string message)
  {
    TemplateRenderer renderer = new TemplateRenderer();
    Console.WriteLine(renderer.Render(message));
  }
}
public class EmailSenderFactory : IObjectFactory<EmailSender>
{
  public EmailSender Create()
  {
    return new EmailSender();
  } 
}
EmailSender emailer = new EmailSender();
emailer.TellEveryone("Hello, World!");

What the MsBuild task will do is this:

  1. Load the target Assemblies using Mono.Cecil
  2. Find implementations of IObjectFactory<T> and add them to the FactoryMap.
  3. Find all instances of new T() for each of those factories and replace them with a call to the Factories.Create<T>(), ignoring calls inside of factories themselves.
  4. Weave the FactoryMap (just the Factory Type and its Object Type) into the Assembly.

So during runtime we can use the FactoryMap that was serialized in step #4 to create the factories and use them to create instances as they're demanded. It is important to note that your objects need default constructors, even though they may never be called after the code is weaved. One can also replace the factory implementations with IoC backed versions, etc...

Why don't you just create a New.Instance<T> method and use that instead of new T() and save yourself the pain of weaving and having a task and all that, moron?

Good question! I mostly did this as an exercise in code weaving using Cecil. It's a great library, although testing code using it can be a little tedious. I'm tossing around some other projects that I'd love to give a shot and this was a good introduction. You could achieve the same thing using reflection to build your factory map and remember to use New.Instance<T>() instead of the new operator in your code. Granted, the manual approach plasters the concern all over the place and weaving keeps the original code free from that. Which may be an OK trade-off for the simplified process.

Another thing to consider, is that perhaps the weaving approach has its applications elsewhere? Use it specifically for creating domain classes to transparently provide domain services? Another idea I've been tossing around is if you're writing code for platforms where garbage collection isn't as performant (xbox for example) you may be able to transparently add object pooling and other patterns after the fact and not clutter up the original code.

I want to release the code anyway, but I'm tired of uploading zip files. All my future source releases will probably be via Google Code or some public svn repository. Stay tuned.... In the meantime, feel free to opine.

by Jacob on Sunday, November 18, 2007 3:49:46 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Sunday, February 18, 2007

Hello everyone. I just wanted to let those who responded to the string literal posts know what was "going on". Basically, we're still trying to find a way that we can release the source to some of our tools. I apologize for dragging my feet. I manage to keep pretty busy. Heh.

I was catching up on the castle-project's mailing list and found this post by Lee Henson. He's tossed together an implementation of a PropertyBag wrapper generator and posted the source. It's very similar to our approach. One main difference is that we do our generation at runtime so we don't have to generate and reference another assembly. We have an IViewFactory interface and a PropertyBagViewFactory implementation that hands them out. In tests we have an IViewFactory that pulls the views out of the MockRepository.

Incidentally, our code that does this lies with some other code for generating Control.Invoke proxies for our System.Windows.Forms view interfaces. It seems we're not the only people who do that particular type of generation. RĂ¼diger Klaehn has an article here about it. I strongly suggest reading it if you do any kind of SWF work.

In the thread I found a link to Brian Romanko's post about his implementation of the controller action/view SiteMap, as well as the PropertyBag wrapper. So just in case anybody gets impatient they can find something to tinker with over there. While his implementation is different from ours, the end result is very similar. I like his idea of generating a property for actions to refer to them without parameters.

I mentioned that for the SiteMap code generation we used CodeDom. CodeDom is great and means we don't have to use StringBuilder to construct C#. It also abstracts the language away. For those who are interested in this kind of code inspection/generation, I strongly suggest taking a look at N Refactory, it's a great library for parsing C#/VB.NET source. It's what we use and I've been incredibly happy with it. The only real hurdle when doing that kind or work is type resolution. I'll try and make a post about that in the near future.

by Jacob on Sunday, February 18, 2007 7:04:16 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Tuesday, January 30, 2007

I figured I might as well continue on the string literal kick I started with my last post and talk about another situation where we've eliminated string literals. Take the following code from inside a MonoRail action method:

PropertyBag["User"] = ourUser;
PropertyBag["TwoStates"] = new string[] { "WA", "CA" };
PropertyBag["IsAdmin"] = true;

String literals, used as keys into dictionaries carry a cetain degree of code smell (for us) and we try to avoid them. It reminds me too much code that does something similar, but in the opposite direction:

int id = Int32.Parse(this.Params["id"])

Thankfully, this kind of code is eliminated when using MonoRail and its SmartDispatchController. We found ourselves thinking of how the same code would look in a SWF application. We would be populating views, only those views would be interfaces that the various forms/controls implemented. Well, this is exactly what we wanted in MonoRail, to wrap the PropertyBag with an interface!

After a few hours playing with Reflection.Emit, I had a code generator that would take an interface:

public interface IEditMyProfileView
{
  string Name { get; set; }
  DateTime Birthday { get; set; }
  IList<TimeZone> TimeZones { get; set; }
}

And produce a class like the following:

public class EditMyProfileViewPropertyBagManipulator : IEditMyProfileView {
  private IDictionary _bag;

  public EditMyProfileViewPropertyBagManipulator(IDictionary bag) {
    _bag = bag;
  }

  public string Name {
    get { return (string)_bag["Name"]; }
    set { _bag["Name"] = value; }
  }
  public DateTime Birthday {
    get { return (DateTime)_bag["Birthday"]; }
    set { _bag["Birthday"] = value; }
  }
  public IList<TimeZone> TimeZones {
    get { return (IList<TimeZone>)_bag["TimeZones"]; }
    set { _bag["TimeZones"] = value; }
  }
}

This has the advantage of keeping our interactions with the PropertyBag as type safe as they can be. Changing the interface, breaks the build. Where as changing the type of a value inserted into the PropertyBag will (hopefully) only break tests if even that. This is another example of us trying to turn run-time failures into compile-time failures.

This kind of thing also makes tests more elegant. Instead of:

Assert.Equals("Jacob", PropertyBag["Name"]);

In our controller tests, we can continue to leverage the use of RhinoMocks to ensure the views are properly initialized:

using (_mocks.Unordered()) {
  _view.Name = "Jacob";
}
_mocks.ReplayAll();
_controller.Action();
_mocks.Verify(_view);

All we've done here is created a mock from the view interface, rather than emitting the wrapper class. Again, another added benefit is if the view changes, compiling the tests will also break. The sooner things break after a change the better, and the build is pretty soon. Although, with ReSharper, it's nice to see red squiggles appear as that's even sooner.

by Jacob on Tuesday, January 30, 2007 8:31:07 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [1]  |  Trackback