Reputation: 1363
how do i use structuremap to give me the same concrete type configured one of 2 different possible ways? For example, i have a class configured to listen to a user queue in one instance, but configured for a facility queue in another instance. Everything else about the object is the same.
I created the object to accept an enum in the constructor, and based on the enum value, the object will listen to either the facility queue or the user queue. So how do I configure structuremap to pass me the two differently configured objects of the same type? The class implements my interface, so it looks like this:
public class Configuration : IConfiguration {
public Configuration(enum configType) {
if (configType == enum.users) {
/* code */
} else if(configType == enum.facilities) {
/* code */
}
}
}
and then, i'm trying to setup the parent class to accept the configuration object twice, once configured for facilities, and once configured for users. How would I do this? I thought maybe I could do it based on when instance name of the two classes, but I can't find anything in the documentation or elsewhere that might explain how to do this. Here's what the parent class looks like:
public class Parent : IParent {
public Parent(IConfiguration facilityConfig, IConfiguration userConfig) {
}
}
So, in the parent class, I would want "facilityConfig" to be an instance of Configuration with enum.facilities passed in, while the "userConfig" object would be an instance of the same Configuration class, but with enum.users passed in. Let me know if what I'm asking doesn't make sense.
Upvotes: 3
Views: 2661
Reputation: 40596
One solution for this problem could be to have two separate configuration classes, instead of one that does the switch based on the enum
value.
You could define the IConfiguration
implementations like this:
public class UsersConfiguration : IConfiguration
{
/* code for user */
}
public class FacilitiesConfiguration : IConfiguration
{
/* code for facilities */
}
and then, in your container configuration you could use Ctor
to specify which types to resolve your constructor arguments to:
var c = new StructureMap.Container();
c.Configure(x =>
{
x.For<IParent>().Use<Parent>()
.Ctor<IConfiguration>("facilityConfig").Is<FacilitiesConfiguration>()
.Ctor<IConfiguration>("userConfig").Is<UsersConfiguration>();
});
After this registration, you can create an IParent
instance:
var p = c.GetInstance<IParent>();
and notice that the two dependencies were correctly set by the container.
Update:
If having different implementations for IConfiguration
is problematic, then you can tell StructureMap exactly how to instantiate a Parent
:
var c = new Container(x =>
{
x.For<IParent>().UseSpecial(i => i.ConstructedBy(ConstructParent));
});
The ConstructParent()
method can be defined like this:
private static IParent ConstructParent()
{
return new Parent(
new Configuration(ConfigType.facilities),
new Configuration(ConfigType.users));
}
If you prefer, you can do this all in one shot:
var c = new Container(x =>
{
x.For<IParent>().UseSpecial(i => i.ConstructedBy(
_ => new Parent(
new Configuration(ConfigType.facilities),
new Configuration(ConfigType.users))));
});
However, in a case like this ("exactly the same apart from this one config value") I would prefer to extract the common definitions in a base (perhaps abstract) class and have two derivatives that only define the config value that differs.
Upvotes: 4