Structure map Generic type scanner
High level
With StructureMap, can I define an assembly validation rule that for the interface IRequestService<T>
will return an object named TRequestService
Examples:
-
FooRequestService
entered whenIRequestService<FooRequest>
requested -
BarRequestService
entered upon requestIRequestService<BarRequest>
More details
I have a generic interface defined
public interface IRequestService<T> where T : Request
{
Response TransformRequest(T request, User current);
}
and then I have several Request objects that implement this interface
public class FooRequestService : IRequestService<Foo>
{
public Response TransformRequest(Foo request, User current) { ... }
}
public class BarRequestService : IRequestService<Bar>
{
public Response TransformRequest(Bar request, User current) { ... }
}
Now I am at the point where I need to register these classes so that the StructureMap knows how to create them because in my controller I want to have the following ctor (which I want the StructureMap to embed FooRequestService
in)
public MyController(IRequestService<Foo> fooRequestService) { ... }
Right now, to work around my problem, I have implemented an empty interface and instead of FooRequestService
implementing a generic interface, I am implementing this empty interface
public interface IFooRequestService : IRequestService<Foo> { }
Then my ctor controllers look like this works with a standard StructureMaps scanner
public MyController(IFooRequestService fooRequestService) { ... }
How do I create a rule with a StructureMap build collector to register all objects named TRequestService with IRequestService<T>
(where T = "Foo", "Bar", etc.) so that I don't have to create these empty interface definitions
To throw something else into the mix where I'm working with the assembly handling StructureMap, there is no reference to the assembly that defines IRequestService<T>
, so some kind of reflection has to be used when doing this. I looked at the answer to " Loading StructureMap for Generic Types with Scan ", but it seems that this answer requires a reference to the assembly that contains the interface definition.
I'm on my way to creating a custom StructureMap.Graph.ITypeScanner, but I'm kind of stuck on what to do there (mostly because I have little experience with reflection).
source to share
You are on the right track with a scanner. Fortunately, there is one built in to StructureMap. Unfortunately, this has not yet been released. Get the latest data from the torso and you will see several new things available in the scanner configuration. Below is an example of your needs.
public class MyRegistry : Registry
{
public MyRegistry()
{
Scan(x =>
{
x.TheCallingAssembly();
//x.AssembliesFromApplicationBaseDirectory();
x.WithDefaultConventions();
x.ConnectImplementationsToTypesClosing(typeof (IRequestService<>));
});
}
}
First you need to tell your scanner configuration which assemblies should be included in the scan. The commented out AssembliesFromApplicationBaseDirectory () method can also help if you are not running the registry per assembly.
To use your generic types in a container, use ConnectImplementationsToTypesClosing .
For an example on how to configure the use of registries when configuring a container see http://structuremap.sourceforge.net/ConfiguringStructureMap.htm
If you like, you can skip using registries altogether and just scan into ObjectFactory.Initialize .
Hope it helps.
source to share