Monday, March 17, 2008

Recursive it is.

Well, for the gtk# presenter injection issue, I determined that I could do the recursive method for in about fifteen lines of code, so I implemented that. I was stumped for quite some time because the recursion wasn't descending at all -- it turns out I was casting widgets to Gtk.Bin when I should have been casting to Gtk.Container.

The code:

public class ViewAttribute : Attribute {}

public class InjectAttribute : Attribute {}

[CastleComponent("bootstrapViews", typeof(BootstrapViews))]
public class BootstrapViews
{
private IWindsorContainer _container;

public BootstrapViews(IWindsorContainer container)
{
_container = container;
}

public void Bootstrap(Widget widget)
{
Container bin = widget as Container;
if (bin == null)
{
return;
}
foreach (Widget child in bin.Children)
{
Bootstrap(child);
}

object[] attrs = bin.GetType().GetCustomAttributes(typeof(ViewAttribute), false);
if (attrs.Length > 0)
{
foreach (FieldInfo field in bin.GetType().GetFields())
{
if (field.GetCustomAttributes(typeof(InjectAttribute), false).Length > 0)
{
field.SetValue(bin, _container.Resolve(field.FieldType));
}
}
}
}
}

Sunday, March 16, 2008

gtksharp and MVP

Switching gears to C#, since, though I love D, I need a working mocks library to write any significant code in it, and dmd bugs prevent dmocks from working correctly.

I'm using gtk#/stetic to create a GUI of moderate complexity, and of course I'm using the Model-View-Presenter pattern. Reminiscent of ASP.NET MVP issues, the main problem is getting a reference to a presenter into a view -- gtk# doesn't use a central object builder that I can hook into; everything happens in a Build method.

So I have three options that I can pursue in achieving a reasonable MVP model:
  1. Each custom widget gets a reference to the Castle container and resolves its presenter that way.
  2. I build my GUI, then do a depth-first traversal of all the components, looking for an attribute set: [View(Type register)] on the class, [Inject] on the presenter(s). Any such classes, I register with the container, then fill in their dependencies. This works for everything that inherits from Gtk.Bin, but I have to copy it for any other gtk classes that my widgets derive from.
  3. Possibly using inheritance, my widgets subclass a SmartPart class and register themselves with a singleton (using the typical singleton pattern) that will register them with the container and fill in dependencies. This means I spend less time at runtime looking at widgets.
Option #1 is not happening.
Option #3, using generics, is reasonably simple, and it works unless I have one view with multiple presenters.
Option #2 is the fully general solution, which I probably won't be implementing. It'd be great, except for the speed, but it's rather yagni.

Of course, the problem with #2 is that my constructors will have to be modified, or the presenters might do something foolish:

public MyWidget()
{
this.Build();
base(whatever);
}
// was:
// public MyWidget() : base(whatever)
// {
// this.Build();
// }

As an aside, has anyone had luck getting CruiseControl.net running on debian?

Wednesday, March 12, 2008

DUnit

I whipped together a quick unittest library, DUnit. Took less than an hour; apparently, SUnit took about two hours to write, so I'm in decent company.

This doesn't offer very much; in particular, there's no measure of progress. That's a deviation from the xUnit standard. And there's no way to control which tests get run. But I'm working on a better version already that offers those features.

On an unrelated note, dmd2 is too unstable to be usable, so dmocks is dead. I'll be updating it to dmd2.011, but probably no further, at least until dmd2 is in late beta or beyond.