Replacement for ObjectFactory?

14,241 views
Skip to first unread message

David Ames

unread,
Jul 21, 2014, 5:55:56 PM7/21/14
to structure...@googlegroups.com
Hey all,

We were using ObjectFactory to access the default container.  EG:

If we needed to do Service Location (which we avoided where possible, we would do)

 public static BreadcrumbTracker ObtainTracker()
        {
            return StructureMap.ObjectFactory.Container.GetInstance<BreadcrumbTracker>();            
        }


In our StructureMapControllerFactory, we would do something like:

 protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
        {
            if ((requestContext == null) || (controllerType == null))
                return null;

            BController controller = (BController) ObjectFactory.Container.GetInstance(controllerType);

      
Now that ObjectFactory is obsolete, what is the recommended replacement/default? I can't seem to find a static class/method to get at the default container.

Cheers,
dave



Luka Cetina

unread,
Jul 22, 2014, 10:12:29 AM7/22/14
to structure...@googlegroups.com

You should pass a container instance in the constructor where you need.

--
You received this message because you are subscribed to the Google Groups "structuremap-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to structuremap-us...@googlegroups.com.
To post to this group, send email to structure...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/structuremap-users/eff18526-a6e7-4e9a-9bbe-25f9aa3f7f62%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jeremy Miller

unread,
Jul 24, 2014, 9:01:25 AM7/24/14
to structure...@googlegroups.com
The "static" part is why I'm wanting to remove ObjectFactory because in practice it creates terrible coupling from your application code to ObjectFactory. You can happily take in IContainer as a constructor argument in any class that needs to do service location or use the Container. That technique even has the advantage of getting the right nested or profiled container that created the object if that's in use.

For frameworks like MVC, Web API, or our own FubuMVC, you just create the container on the fly in the bootstrapping and ensure that it's disposed on application startup (FubuMVC does this for you).

- Jeremy 


On Tuesday, July 22, 2014 9:12:29 AM UTC-5, Luka wrote:

You should pass a container instance in the constructor where you need.

On Jul 21, 2014 11:55 PM, "David Ames" <david...@gmail.com> wrote:
Hey all,

We were using ObjectFactory to access the default container.  EG:

If we needed to do Service Location (which we avoided where possible, we would do)

 public static BreadcrumbTracker ObtainTracker()
        {
            return StructureMap.ObjectFactory.Container.GetInstance<BreadcrumbTracker>();            
        }


In our StructureMapControllerFactory, we would do something like:

 protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
        {
            if ((requestContext == null) || (controllerType == null))
                return null;

            BController controller = (BController) ObjectFactory.Container.GetInstance(controllerType);

      
Now that ObjectFactory is obsolete, what is the recommended replacement/default? I can't seem to find a static class/method to get at the default container.

Cheers,
dave



--
You received this message because you are subscribed to the Google Groups "structuremap-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to structuremap-users+unsub...@googlegroups.com.
To post to this group, send email to structuremap-users@googlegroups.com.

David Ames

unread,
Jul 24, 2014, 4:24:35 PM7/24/14
to structure...@googlegroups.com
Thanks Jeremy,

 After trying to get SM to work in a windows service with nHibernate, managing UoW, etc I can see exactly what you mean by coupling.

Quick Question - for object's that have their lifetime managed by the MVC framework (eg, filters, view-models/iValidatableObject etc), what is the preferred way to do DI with SM? Is there a way to declare the dependencies in the constructor and have MVC construct them with SM?

dave

philip Johnson

unread,
Jul 26, 2014, 12:32:33 PM7/26/14
to structure...@googlegroups.com
Do you have an example somewhere that we can look at for an example of this in MVC?  I'm right now using StructureMap.ObjectFactory.GetNamedInstance<T>("InstanceName") and having a difficult time finding a suitable replacement for that line of code.  This is being used inside a controller, are you saying that i should override the controller constructor to take an IContainer parameter?


On Thursday, July 24, 2014 6:01:25 AM UTC-7, Jeremy Miller wrote:
The "static" part is why I'm wanting to remove ObjectFactory because in practice it creates terrible coupling from your application code to ObjectFactory. You can happily take in IContainer as a constructor argument in any class that needs to do service location or use the Container. That technique even has the advantage of getting the right nested or profiled container that created the object if that's in use.

For frameworks like MVC, Web API, or our own FubuMVC, you just create the container on the fly in the bootstrapping and ensure that it's disposed on application startup (FubuMVC does this for you).

- Jeremy 

On Tuesday, July 22, 2014 9:12:29 AM UTC-5, Luka wrote:

You should pass a container instance in the constructor where you need.

On Jul 21, 2014 11:55 PM, "David Ames" <david...@gmail.com> wrote:
Hey all,

We were using ObjectFactory to access the default container.  EG:

If we needed to do Service Location (which we avoided where possible, we would do)

 public static BreadcrumbTracker ObtainTracker()
        {
            return StructureMap.ObjectFactory.Container.GetInstance<BreadcrumbTracker>();            
        }


In our StructureMapControllerFactory, we would do something like:

 protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
        {
            if ((requestContext == null) || (controllerType == null))
                return null;

            BController controller = (BController) ObjectFactory.Container.GetInstance(controllerType);

      
Now that ObjectFactory is obsolete, what is the recommended replacement/default? I can't seem to find a static class/method to get at the default container.

Cheers,
dave



--
You received this message because you are subscribed to the Google Groups "structuremap-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to structuremap-users+unsub...@googlegroups.com.
To post to this group, send email to structure...@googlegroups.com.

Jeremy Miller

unread,
Jul 29, 2014, 8:24:13 PM7/29/14
to structure...@googlegroups.com
@Philip,

If you're wanting to do service location within a controller, you can take in the real container itself in your constructor function like so:

public class MyController
{
    public MyController(IContainer container)
    {
        // keep a reference to container and you can use it to do any kind of service resolution
        
    }
}

I'd say this is really a better solution anyway because it sets you up to work with nested containers or one off container configurations in testing instead of the potentially harmful coupling to the static ObjectFactory.

If you're up on SM 3.0.5+, you can also take in Func<string, T> where T is whatever type you want to build later so you could completely decouple yourself from StructureMap if you want.

Thanks,

Jeremy

Jeremy Miller

unread,
Jul 29, 2014, 8:30:21 PM7/29/14
to structure...@googlegroups.com
That's a little bit more of an MVC question than a StructureMap question per se. Anything that MVC itself resolves from its service locator (ControllerFactory) supports constructor injection. Anything built by the FX itself probably has to be further configured by Container.BuildUp() and setter injection.

It's dead, but FubuMVC handled container integration much better than MVC in my very biased opinion;)

You might ask Jimmy Bogard (@jbogard) about the MVC integration as he's much more likely to know than I.

Thanks,

Jeremy

Shawn de Wet

unread,
Aug 11, 2014, 12:02:37 AM8/11/14
to structure...@googlegroups.com
Hi Jeremy,
Could you please advise how I would convert the following to the new approach?

public class MvcApplication : System.Web.HttpApplication
    {
        public IContainer Container
        {
            get
            {
                return (IContainer)HttpContext.Current.Items["_container"];
            }
            set
            {
                HttpContext.Current.Items["_container"] = value;
            }
        }

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            DependencyResolver.SetResolver(new SMDependencyResolver(() => Container ?? ObjectFactory.Container));

            ObjectFactory.Configure(cfg =>
            {
                cfg.AddRegistry(new StandardRegistry());
                cfg.AddRegistry(new ControllerRegistry());
                cfg.AddRegistry(new ActionFilterRegistry(() => Container ?? ObjectFactory.Container));
                cfg.AddRegistry(new MvcRegistry());
                cfg.AddRegistry(new TaskRegistry());
                cfg.AddRegistry(new ModelMetadataRegistry());
            });

            using (var container = ObjectFactory.Container.GetNestedContainer())
            {
                foreach (var task in container.GetAllInstances<IRunAtStartup>())
                    task.Execute();
            }
        }

        public void Application_BeginRequest()
        {
            //This approach implements ContainerPerRequest, so nested actions use the same controller as the parent Request action
            // -- the benefit is that a single container allows there to be one DbContext instantiated by the one Container.
            Container = ObjectFactory.Container.GetNestedContainer();
            foreach (var task in Container.GetAllInstances<IRunOnEachRequest>())
                task.Execute();
        }

        public void Application_EndRequest()
        {
            try
            {
                foreach (var task in Container.GetAllInstances<IRunAfterEachRequest>())
                    task.Execute();
            }
            finally
            {
                Container.Dispose();
                Container = null;
            }

        }

        public void Application_Error()
        {
            foreach (var task in Container.GetAllInstances<IRunOnError>())
                task.Execute();

        }
    }

If the ObjectFactory was the mechanism of instantiating a new Container...how do I change the above to instantiate a Container without ObjectFactory?
Thanks,
--Shawn.

Jeremy Miller

unread,
Aug 11, 2014, 9:43:24 AM8/11/14
to structure...@googlegroups.com
It's just something like:

var container = new Container(x => {

});

Jeremy Miller

unread,
Aug 11, 2014, 9:44:40 AM8/11/14
to structure...@googlegroups.com
Sorry, hit send by accident before. Just new up the Container object directly. It uses the same syntax as ObjectFactory.Initialize(), and ObjectFactory is just a static facade over Container anyway.

Thanks,

Jeremy


On Sunday, August 10, 2014 11:02:37 PM UTC-5, Shawn de Wet wrote:

Vahid N.

unread,
Oct 19, 2014, 6:07:37 PM10/19/14
to structure...@googlegroups.com
Removing ObjectFactory will break a lot of service locator scenarios.
This is the simplified version of ObjectFactory for the record!

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
         });
     }
}

David Ames

unread,
Nov 22, 2014, 10:15:58 PM11/22/14
to structure...@googlegroups.com

For IoC in Validation Attributes or iValidatableObjects, you can use this code here: http://www.amescode.com/using-structuremap-for-dependency-injection-in-mvc-validation-attributes-and-ivalidatableobjects/

Posting as a reference for when someone stumbled on this thread.

rekna

unread,
Dec 18, 2014, 1:35:03 AM12/18/14
to structure...@googlegroups.com
Is there a way to get statically the current nested container ? I want to refactor a large application, that currently uses ObjectFactory.GetInstance throughout the code. None of the classes have currently constructor injection, some static classes use ObjectFactory.GetInstance as well, a lot classes are not created by structuremap, but use ObjectFactory.GetInstance. Converting all code at once to constructor injection is impossible, I need a intermediate solution where I can replace ObjectFactory.GetInstance with a replacement that fetches the object from the current nested container. And it should have to work in different scenario's, because the application is MVC, Windows service, Wcf services...


On Thursday, July 24, 2014 3:01:25 PM UTC+2, Jeremy Miller wrote:
The "static" part is why I'm wanting to remove ObjectFactory because in practice it creates terrible coupling from your application code to ObjectFactory. You can happily take in IContainer as a constructor argument in any class that needs to do service location or use the Container. That technique even has the advantage of getting the right nested or profiled container that created the object if that's in use.

For frameworks like MVC, Web API, or our own FubuMVC, you just create the container on the fly in the bootstrapping and ensure that it's disposed on application startup (FubuMVC does this for you).

- Jeremy 

On Tuesday, July 22, 2014 9:12:29 AM UTC-5, Luka wrote:

You should pass a container instance in the constructor where you need.

On Jul 21, 2014 11:55 PM, "David Ames" <david...@gmail.com> wrote:
Hey all,

We were using ObjectFactory to access the default container.  EG:

If we needed to do Service Location (which we avoided where possible, we would do)

 public static BreadcrumbTracker ObtainTracker()
        {
            return StructureMap.ObjectFactory.Container.GetInstance<BreadcrumbTracker>();            
        }


In our StructureMapControllerFactory, we would do something like:

 protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
        {
            if ((requestContext == null) || (controllerType == null))
                return null;

            BController controller = (BController) ObjectFactory.Container.GetInstance(controllerType);

      
Now that ObjectFactory is obsolete, what is the recommended replacement/default? I can't seem to find a static class/method to get at the default container.

Cheers,
dave



--
You received this message because you are subscribed to the Google Groups "structuremap-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to structuremap-users+unsub...@googlegroups.com.
To post to this group, send email to structure...@googlegroups.com.

Jimmy Bogard

unread,
Dec 19, 2014, 8:48:13 AM12/19/14
to structuremap-users
No, that's defeating the intent of a nested container. The whole point of a nested container is that you have a scope in which you can reason about. Things that need the "Current Child Container" would simply take an IContainer as a dependency.

To unsubscribe from this group and stop receiving emails from it, send an email to structuremap-us...@googlegroups.com.

To post to this group, send email to structure...@googlegroups.com.

rekna

unread,
Dec 19, 2014, 2:02:49 PM12/19/14
to structure...@googlegroups.com
I agree, but refactoring a large application in one go is risky and very time consuming... I want a kind of simpler migration path so I can refactor parts of the application.
To unsubscribe from this group and stop receiving emails from it, send an email to structuremap-users+unsubscribe@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "structuremap-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to structuremap-users+unsub...@googlegroups.com.
To post to this group, send email to structure...@googlegroups.com.

rekna

unread,
Dec 20, 2014, 7:49:11 AM12/20/14
to structure...@googlegroups.com
To make things worse... what if the project uses other assemblies written by other people that still use ObjectFactory.GetInstance. It's impossible to ask them to change all their code, and if they don't and I can't replace the implementation of ObjectFactory.GetInstance, I never can refactor my project.

Apart from that, maybe CallContext.LogicalGetData and LogicalSetData maybe can be used in non http applications (like windows services) to store and retrieve the current nested container?


On Friday, December 19, 2014 2:48:13 PM UTC+1, Jimmy Bogard wrote:
To unsubscribe from this group and stop receiving emails from it, send an email to structuremap-users+unsubscribe@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "structuremap-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to structuremap-users+unsub...@googlegroups.com.
To post to this group, send email to structure...@googlegroups.com.

Albert Weinert

unread,
Dec 20, 2014, 9:38:35 AM12/20/14
to structure...@googlegroups.com
First @Jeremny. Kill ObjectFactory …

Second,  it may possible to write a compat assembly. With some redirects.

Third it es definitely possible to write your own ObjectFactory.GetInstance and make a type redirect from 
SM to your implementation.


Are, the easiest way at all. Use StructureMap 3.x.

Best Regards

Albert

GMCS

unread,
Dec 3, 2015, 10:29:18 AM12/3/15
to structuremap-users
Hi All,

I am using following code in my project. My all code is working. But In my some of test cases are failing If I run them using Run All test case Button in visual studio.
If I run the test cases individually then that test cases getting passed.
I am not getting what to do with this type of wired behavior. 
Failing test cases gives the object null references. I am not getting what is the problem and its solution.

Note: I am running test cases in parallel.

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


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

        private static Container DefaultContainer()
        {
            return _container;
        }

        public static void Initialize<T>() where T : Registry, new()
        {
            _container = new Container(x =>
            {
                x.AddRegistry<T>();
            });

Vahid N.

unread,
Dec 3, 2015, 11:42:07 AM12/3/15
to structuremap-users

My version, produces a lazy loaded thread safe singleton, but your `Initialize` method is not thread safe. Try:

public static class StructureMapObjectFactory
{
    private static readonly Lazy<Container
> _containerBuilder =
        new Lazy<Container>(() => new Container(), LazyThreadSafetyMode.ExecutionAndPublication);
 
    public static IContainer Container
    {
        get { return _containerBuilder.Value; }
    }
 
    public static void Initialize<T>() where T : Registrynew()
    {
        Container.Configure(x =>
        {
            x.AddRegistry<T>();
        });
    }
}

Jhon Pierre

unread,
Jan 3, 2017, 3:19:13 PM1/3/17
to structuremap-users
And how could I access the "ObjectFactory.GetInstance<>()" old method in a Data Access Layer (first layer) if the StructureMapObjectFactory 
class is in the Web Site Project (presentation layer)???

How could I use the IContainer from the Data Access Layer???

Jeremy Miller

unread,
Jan 3, 2017, 3:47:40 PM1/3/17
to structure...@googlegroups.com
If your data access objects are resolved from StructureMap, you can happily take in “IContainer” in your class’s constructor
function and use that. The container injected will always be the instance of Container that built the object.

I’d strongly recommend against using any kind of static ObjectFactory like wrapper about IContainer anywhere but in the code that bootstraps your application.

- Jeremy


-- 
You received this message because you are subscribed to the Google Groups "structuremap-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to structuremap-us...@googlegroups.com.

To post to this group, send email to structure...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages