Removing a default instance type from StructureMap at runtime
Is it possible to remove a mappi开发者_Go百科ng at run time? I can add one easily enough with:
ObjectFactory.Configure(ce =>
ce.ForRequestedType<IDateAdjuster>().
TheDefaultIsConcreteType<DateAdjusterForTest>());
and I can check to see if a mapping exists with
ObjectFactory.Model.HasDefaultImplementationFor<IDateAdjuster>()
but I can't seem to remove a default instance type. I tried this
var config = ObjectFactory.Model.PluginTypes
.FirstOrDefault(pt => pt.PluginType == typeof(IDateAdjuster));
if (config != null) {config.Default = null;}
But this isn't working.
What the interface does is hide away the DateTime.Now
and DateTime.Today
properties so that during testing, in particular integration and user acceptance, the system can be configured to shift the current date and time as it sees it.
What I was trying to do was check to see if there was a default implementation of the interface, if there was then I'd create and call it, if not then I'd just use DateTime.Now
and DateTime.Today
As it seems that I can't tell structure map to remove the default type, so I've now added a new default implementation of the interface and extended the interface to have a property to indicate if it's active. The default implementation indicates that the interface is not active. So now I can always get an instance and then check if I want to use it.
The system has quite a bit of date and time specific behavior and so the client needs to be able to test how the system behaves at different dates and times. They login to the admin section and then set the date and time to the appropriate values, then I switch the default implementation to the test implementation that makes the appropriate adjustment.
As it is only the implementation of the interface that changes I just switch which implementation I want to use when the client admin sets it, and then reset it when they are done
Changing the IoC configuration at runtime is a bit scary IMO. Perhaps using a factory would be cleaner solution. For instance:
public interface IOptionalFactory
{
IOptional GetInstance(IPrinciple currentUser);
}
You can inject the IOptionalFactory
instead of an IOptional
interface and let the factory return different instances based on the supplied user information.
So if the switch is controlled by something the user changes, I am guessing its in the database or maybe session? If this is the case you can use the conditional construction feature of StructureMap to do this:
var container = new Container(x =>
{
x.InstanceOf<IDateAdjuster>().Is.Conditional(o =>
{
o.If(c => c.GetInstance<IUserSettings>()
.UseTestDateAdjuster).ThenIt.Is.OfConcreteType<DateAdjusterForTest>();
o.TheDefault.Is.OfConcreteType<DateAdjuster>();
});
});
IUserSettings could be anything that is registered in your contain that will tell you if the user has set the date and time in the admin section.
See this blog for more details: http://codebetter.com/jeremymiller/2009/01/19/conditional-object-construction-in-structuremap-i-e-fun-with-lambdas/
精彩评论