important; I'm really looking for a StructureMap
answer here. Please don't say how to do it with Windsor, Spring, Unity, or any of the others.
I'm playing with StructureMap
for IoC - and basically my aim is to have a "default" profile that defines the core types, and a number of named profiles that override/extend this. I think that profiles can do this, but I simply can't get it to work either through the xml or the code APIs. In particular, if I try to load a container for a profile:
container = new Container();
container.SetDefaultsToProfile(profile);
Then I get "Requested Profile {name} cannot be found", despite the fact that I clearly called CreateProfile
in the initialize (with that name).
Am I barking up the wrong tree?
(also posted to user-group)
What I ideally want is to be able to define the standard (/default) types, and then for a range of different named configurations, override some of the settings - i.e. if I had
IFoo
=> Foo
, IBar
=> Bar
IFoo
=> SpecialFoo
I believe this could map to 2 containers, loaded using named profiles.
The purpose being that if I ask either container for an IBar
, I get a
Bar
- but configA returns a Foo
(for IFoo
), where-as configB returns a
SpecialFoo
.
Can somebody give me a clue how I can configure this? Either xml or code is fine... I just want it to work. All I need is interface-to- concrete-type mappings (no special config/property settings).
The trick is to make sure every single profile as at least a rule defined in it. If you don't specify a rule (configA) it won't create/see the profile.
Given these classes:
public interface IFoo { string SayHello(); }
public class Foo : IFoo { public string SayHello() { return "Hello"; } }
public class SpecialFoo : IFoo { public string SayHello() { return "Hello Special"; } }
public interface IBar { }
public class Bar : IBar { }
public interface IDummy { }
public class Dummy : IDummy{ }
You can define this registry:
public class MyRegistry : Registry
{
protected override void configure()
{
ForRequestedType<IBar>().TheDefault.Is.OfConcreteType<Bar>();
ForRequestedType<IFoo>().TheDefault.Is.OfConcreteType<Foo>();
CreateProfileNotEmpty("configA");
CreateProfileNotEmpty("configB")
.For<IFoo>().UseConcreteType<SpecialFoo>();
}
StructureMap.Configuration.DSL.Expressions.ProfileExpression CreateProfileNotEmpty(string profile)
{
return CreateProfile(profile)
.For<IDummy>().UseConcreteType<Dummy>();
}
}
And it will work with these tests:
[TestMethod]
public void TestMethod1()
{
var container = new Container(new MyRegistry());
Assert.IsNotNull(container.GetInstance<IBar>());
Assert.AreEqual("Hello", container.GetInstance<IFoo>().SayHello());
container.SetDefaultsToProfile("configB");
Assert.IsNotNull(container.GetInstance<IBar>());
Assert.AreEqual("Hello Special", container.GetInstance<IFoo>().SayHello());
container.SetDefaultsToProfile("configA");
Assert.IsNotNull(container.GetInstance<IBar>());
Assert.AreEqual("Hello", container.GetInstance<IFoo>().SayHello());
}
if you replace CreateProfileNotEmpty with simple CreateProfile, it will fail on the line that sets the default to configA.
Watch this video, he shows another way of doing the "default" profile and having other named profiles that would act as the variations.
http://www.dimecasts.net/Casts/CastDetails/135
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With