Given concrete classes and interfaces having names that don't match
Harvester_JohnDeere_Parsley : AbstractMachine, IParsleyHarvester
Harvester_NewHolland_Sage : AbstractMachine, ISageHarvester
Harvester_Kubota_Rosemary : AbstractMachine, IRosemaryHarvester
where the interfaces have a common parent
IParsleyHarvester : ISpiceHarvester
ISageHarvester : ISpiceHarvester
IRosemaryHarvester : ISpiceHarvester
how can StructureMap be configured so that instances of I...Harvester can be injected into the constructor e.g.
public ParsleyField(IParsleyHarvester parsleyHarvester)
without having to configure each pair individually in the Registry? e.g.
For<ISageHarvester>().Use<Harvester_NewHolland_Sage>();
I've tried scanning
Scan(x =>
{
x.AssemblyContainingType<Harvester_Kubota_Rosemary>();
x.AddAllTypesOf<ISpiceHarvester>();
but the I...Harvester interfaces don't get mapped.
Thanks!
edit:
Both answers work. @jeroenh's has the advantage that guard clauses can be added to exclude classes (for whatever reason). Here's an example based on @Mac's answer to this question.
public class HarvesterConvention : StructureMap.Graph.IRegistrationConvention
{
public void Process(Type type, Registry registry)
{
// only interested in non abstract concrete types
if (type.IsAbstract || !type.IsClass)
return;
// Get interface
var interfaceType = type.GetInterface(
"I" + type.Name.Split('_').Last() + "Harvester");
if (interfaceType == null)
throw new ArgumentNullException(
"type",
type.Name+" should implement "+interfaceType);
// register (can use AddType overload method to create named types
registry.AddType(interfaceType, type);
}
}
usage:
Scan(x =>
{
x.AssemblyContainingType<Harvester_Kubota_Rosemary>();
x.Convention<HarvesterConvention>();
x.AddAllTypesOf<ISpiceHarvester>();