Reputation: 34800
Is it possible to pass the requesting type as a parameter when configuring a StructureMap container.
For example:
container.Configure(x => {
x.For<ILogger>().Use(new TestLogger(log.Add, requestingType));
});
Where requesting type is the consuming object's type:
public class SomeClass
{
private readonly ILogger logger;
public SomeClass(ILogger logger)
{
this.logger = logger;
}
}
So the type passed to the logger would be SomeNamespace.SomeClass.
Thanks, Ben
Upvotes: 3
Views: 1327
Reputation: 2661
You can easily gain access to the requested type by using StructureMap's IContext.
ObjectFactory.Configure(
x => {
x.For<ILogger>().Use( context => new TestLogger( context.ParentType ) );
} );
In the above statement, context.ParentType returns the type being created by StructureMap.
Jeremy Miller has covered this topic in a blog post as well. The article uses outdated syntax but it is still relevant: http://codebetter.com/jeremymiller/2009/01/15/using-the-build-session-in-structuremap/
If you would like to inspect all of the available properties in the IContext, you can use an anonymous function and set a breakpoint on the return line like so:
ObjectFactory.Configure(
x => {
x.For<ILogger>()
.Use( context =>
{
// Set breakpoint here and inspect the context
return new TestLogger( context.ParentType );
} );
} );
Update:
Make sure to use the .AlwaysUnique() ( which is equivalent to the older syntax of .CacheBy( InstanceScope.Unique ) ) otherwise StructureMap will cache the first request of ILogger which will result in the original logger being injected into all subsequent requests for the ILogger during a single GetInstance() call.
This can easily occur if you have nested classes that each require an ILogger so a request for ObjectFactory.GetInstance< ISomeClass >() will result in an ILogger being created for the deepest class in the hierarchy and then all other classes will receive that same instance of ILogger which is most likely what you do not want to happen.
So taking this update and Ben's tip into consideration, here's a better solution:
x.For<ILogger>()
.AlwaysUnique()
.Use( c => new TestLogger( c.ParentType ?? c.BuildStack.Current.ConcreteType ) );
Upvotes: 3
Reputation: 2160
First I want to point out a potential gotcha, registering an instance with Use(new Type()) causes that instance to be registered as a singleton. To avoid this, you can do Use(() => new Type()).
Here is how you get the requested type at configuration time:
container.Configure(x => {
x.For<ILogger>().Use(c => new TestLogger(log.Add, c.Root.RequestedType));
});
Upvotes: 0
Reputation: 34800
I found a solution here
Basically we changed the ILogger interface to ILogger<T>
and made use of the generic type inference feature in StructureMap.
Strictly speaking this doesn't answer my question of whether I can get the requesting type so if you know how to do this please respond - it would be useful to know.
Upvotes: 0