How can I use StructureMap to resolve to an appropriate implementation of an interface based on a name stored in an attribute?
In my project, I have many different kinds of widgets, each descending from IWidget
, and each decorated with an attribute specifying the kind of associated element.
To illustrate:
[Configuration("header")]
public class HeaderWidget : IWidget { }
[Configuration("linegraph")]
public class LineGraphWidget : IWidget { }
When processing my (XML) configuration file, I want to obtain an instance of the appropriate concrete class based on the name of the element I'm processing.
public IWidget CreateWidget(XElement definition)
{
var kind = definition.Name.LocalName;
var widget = // What goes here?
widget.Configure(definition);
return widget;
}
Each definition should result in a different widget being created - I don't need or want the instances to be shared.
In the past I've written plenty of code to do this kind of thing manually, including writing a custom "roll-your-own" IoC container for one project. However, one of my goals with this project is to become proficient with StructureMap instead of reinventing the wheel.
I think I've already managed to set up automatic scanning of assemblies so that StructureMap knows about all my IWidget implementations:
public class WidgetRegistration : Registry
{
public WidgetRegistration()
{
Scan(
scanner =>
{
scanner.AssembliesFromApplicationBaseDirectory();
scanner.AddAllTypesOf<IWidget>();
});
}
}
However, this isn't registering the names of my widgets with StructureMap. What do I need to add to make my scenario work?
(While I am trying to use StructureMap in this project, an answer showing me how to solve this problem with a different DI/IoC tool would still be valuable.)
Update
I'm pretty sure that the consumption side involves calling GetNamedInstance
like this:
public IWidget CreateWidget(XElement definition)
{
var kind = definition.Name.LocalName;
var widget = ObjectFactory.GetNamedInstance<IWidget>(kind);
widget.Configure(definition);
return widget;
}
So the remaining piece of the puzzle is how to automagically register the types within my WidgetRegistration class.