How to use Container instead of ObjectFactory in StructureMap ServiceActivator?
Asked Answered
B

1

37

When implementing DI in WebAPI with StructureMap, we used the ServiceActivator found in


public class ServiceActivator : IHttpControllerActivator
{
    public ServiceActivator(HttpConfiguration configuration) {}    

    public IHttpController Create(HttpRequestMessage request,
           HttpControllerDescriptor controllerDescriptor, Type controllerType)
    {
        var controller = ObjectFactory.GetInstance(controllerType) as IHttpController;
        return controller;
    }
}

But now with the new StructureMap, my ReSharper suggested:

Class 'StructureMap.ObjectFactory' is obsolete: ObjectFactory will be removed in a future 4.0 release of StructureMap. Favor the usage of the Container class for future work

The intellisense on Container gave me only very limited information.

How are we supposed to rewrite our ServiceActivator with the Container class?

Bullpup answered 28/8, 2014 at 14:9 Comment(0)
S
39

The static stuff is going away. If your not using a Service Locator of some type you're going to have implement your own "ObjectFactory" as referenced here:

public static class ObjectFactory
{
    private static readonly Lazy<Container> _containerBuilder =
            new Lazy<Container>(defaultContainer, LazyThreadSafetyMode.ExecutionAndPublication);

    public static IContainer Container
    {
       get { return _containerBuilder.Value; }
    }

     private static Container defaultContainer()
     {
        return new Container(x =>
        {
               // default config
         });
     }
}

Update: My previous answer was wrong. Thanks @JoeMighty for the heads up.

Standee answered 28/8, 2014 at 14:13 Comment(14)
Surely this just creates a new instance of an empty container? From my experience that seems to be the case.Kermes
@JoeMightly To quote the author "ObjectFactory is just a static facade over Container anyway". However, I will throw up a gist later today that proves this.Standee
I've read this too; however I seem to end up with an empty container. A gist demonstrating this would be greatly appreciated!Kermes
@JoeMighty You are correct! I used Service Locator and/or the built in MVC DependencyResolver for resolution with SM3, so I never ran into this problem. However after several tests, as far as I can tell I end up with empty containers like you noted.Standee
Ok, thanks for clarifying and updating your answer! It's good to know I wasn't going crazy. Another pattern I've noticed is to store the container in HttpContext.Items.Kermes
why is ObjectFactory going away? I understand that most of its usages are wrong: service location anti-pattern; using a top-level container on a nested-container environment; (...). In some cases, such as having an IHttpModule for instance, that needs to get something from the IContainer and it's not DI-friendly, what's the suggested approach? I don't want to move my composition root and I want to use the same container contextPatience
@RicardoRodrigues I believe the gist is that ObjectFactory promotes the service locator anti patternCandiecandied
@eddiegroves An IoC container is a very sharp tool, you can't just polish the edges, needs to be sharp, it's meant to be used by experienced developers. If you take the sharpness, this happens.Patience
Service location is not and has not ever been an anti-pattern. Usage of the pattern incorrectly does not make the pattern itself wrong.Downcome
What is supposed to go in //default config? I'm just trying to upgrade structuremap, and now our entire applications codebase is broken! This is going to take days of work.Medullary
@TylerJones Are you using a Registry to config SM?Standee
Yes, we are using a registry.Medullary
@TylerJones just add this then: x.AddRegistry<MyRegistry>(); where it says // default config MyRegistry being your registry typeStandee
@TylerJones let me know if that worked or not, I can help you offline if you still get stuckStandee

© 2022 - 2024 — McMap. All rights reserved.