views:

166

answers:

2

I have an existing ASP.NET MVC application and am using StructureMap as my IOC container of choice. Currently when a controller needs an IMembershipProvider I use StructureMap to inject a concrete instance in the controller's constructor based on the BuyerMembershipProvider configuration from my web.config file as in the below solution code:

ObjectFactory.Initialize(x =>
{
        x.ForRequestedType<IMembershipService>().TheDefaultIsConcreteType<AccountMembershipService>();
    x.ForRequestedType<IFormsAuthentication>().TheDefaultIsConcreteType<FormsAuthenticationService>();
    x.ForRequestedType<MembershipProvider>().TheDefault.IsThis(SecurityProvider.Providers["BuyerMembershipProvider"]);
});

This works fine. However, it is bound to the "buyer" user type. Seller information is stored in a different database and will have different tables to store membership information. Essentially, I would like to be able to inject either a BuyerMembershipProvider or a SellerMembership Provider based on context and have the following in my objectfactory initialization:

x.ForRequestedType<MembershipProvider>().TheDefault.IsThis(SecurityProvider.Providers["BuyerMembershipProvider"]);
x.ForRequestedType<MembershipProvider>().TheDefault.IsThis(SecurityProvider.Providers["SellerMembershipProvider"]);

Is it possible to decide between two concrete implementations when initializing the objectfactory?

Any help is greatly appreciated, Thanks in advance! JP

+1  A: 

The major mechanisms in choosing between different implementations would be via

  • named instance
  • choosing a certain ctor dependency
  • a conditional expression in StructureMap.

You can't state 2 defaults for a given type (which should be obvious), but you can name an instance and say under which circumstances you want to use it.

A named instance is defined e.g. like this:

InstanceOf<IApplicationModule>()
  .Is.OfConcreteType<BusinessProcessSupport>()
  .WithName("BusinessProcessSupport");

Here is an example where a named instance is used in fulfilling a certain ctor dependency:

ForRequestedType<MenuStripModule>()
  .CacheBy(InstanceScope.Singleton)
  .TheDefault.Is.OfConcreteType<MenuStripModule>()
  .CtorDependency<ICommandInfoProvider>()
    .Is(i => i.TheInstanceNamed("Functions"));

And finally you can have a look here at a (somewhat nasty) StructureMap expression that uses the conditional capabilities: http://realfiction.net/Content/Entry/142 Please note that you are using the StructureMap 2.5.* syntax. 2.6.* is out which has modified the configuration grammar to be more concise and to the point.

flq
Thanks, i'll check it out and let you know how it works for me. nice blog by the way!
JP
+1  A: 

You could define a factory lambda expression which will do your deciding at runtime.

var securityProviderName = ConfigurationManager.AppSettings["securityProvider"];
bool requireBuyerProvider = (securityProviderName == "Buyer");

ObjectFactory.Initialize(x =>
{
    x.For<MembershipProvider>().Use(c=>
    {
        if (requireBuyerProvider)
            c.GetInstance<SellerMemberShipProvider>();
        else
            c.GetInstance<BuyerMembershipProvider>();
    });
});
KevM