Some new ways to build objects in StructureMap with less configuration

I’m getting close to code complete on the forthcoming 2.5 release of StructureMap and I’m focusing on ease of use features and fullblown interception support for AOP tooling (runtime AOP to be provided by something else though).  StructureMap has had some support in the last couple releases to “fill” a concrete class with dependencies by calling ConcreteClass concreteClass = ObjectFactory.FillDependencies<ConcreteClass>().  The advantage being that you didn’t have to explicitly register ConcreteClass with the configuration. 

After

  1. Having somebody ask me how to do it
  2. Seeing a demo of another container do this (I’m not sure about my “NDA” on this, so I’m not gonna say which)
  3. Basically wanting a better way to do this for my current project

I decided to just add it. 

As of today (in the trunk at least) you can simply request a concrete class through the normal ObjectFactory.GetInstance<T>() method, and if StructureMap can resolve the dependencies, ObjectFactory will happily return the class requested.  Taking it a step farther, say you have a class with this constructor:  public TradePresenter(Trade trade, ITradeView view, ITradeRepository repository).  You can also do this now:  TradePresenter presenter = ObjectFactory.With<Trade>(someTradeVariable).GetInstance<TradePresenter>() and you can get a TradePresenter object built with all of its dependencies (an ITradeView & ITradeRepository) plus pass the exact instance of the Trade class into the TradePresenter’s constructor function.

All of this is in the Subversion trunk.  If you feel like downloading it out of SVN and playing with it, I’d appreciate the feedback.  Below is the unit test I’m using to prove out the implicit configuration:

        [Test]
        public void CanBuildConcreteTypesThatAreNotPreviouslyRegistered()
        {
            // Create a new InstanceManager that has a default instance configured for only the
            // IProvider interface.  InstanceManager is the real "container" behind ObjectFactory
            Registry registry = new Registry();
            registry.ForRequestedType<IProvider>().TheDefaultIsConcreteType<Provider>();
            InstanceManager manager = (InstanceManager) registry.BuildInstanceManager();
 
            // Now, have that same InstanceManager create a ClassThatUsesProvider.  StructureMap will
            // see that ClassThatUsesProvider is concrete, determine its constructor args, and build one 
            // for you with the default IProvider.  No other configuration necessary.
            ClassThatUsesProvider classThatUsesProvider = manager.CreateInstance<ClassThatUsesProvider>();
            Assert.IsInstanceOfType(typeof(Provider), classThatUsesProvider.Provider);
        }
 

Here’s another example of using the new explicit arguments functionality.  The relevant code is bolded:

        [Test]
        public void NowDoItWithObjectFactoryItself()
        {
            StructureMapConfiguration.ForRequestedType<ExplicitTarget>().TheDefaultIs(
                Registry.Instance<ExplicitTarget>()
                    .UsingConcreteType<ExplicitTarget>()
                    .Child<IProvider>().IsConcreteType<RedProvider>()
                    .WithProperty("name").EqualTo("Jeremy")
                );
 
            ObjectFactory.Reset();
 
            // Get the ExplicitTarget without setting an explicit arg for IProvider
            ExplicitTarget firstTarget = ObjectFactory.GetInstance<ExplicitTarget>();
            Assert.IsInstanceOfType(typeof (RedProvider), firstTarget.Provider);
 
            // Now, set the explicit arg for IProvider
            BlueProvider theBlueProvider = new BlueProvider();
            ExplicitTarget secondTarget = ObjectFactory.With<IProvider>(theBlueProvider).GetInstance<ExplicitTarget>();
            Assert.AreSame(theBlueProvider, secondTarget.Provider);
        }

Feedback on the syntax and/or usefulness of these features would be very appreciated.

About Jeremy Miller

Jeremy is the Chief Software Architect at Dovetail Software, the coolest ISV in Austin. Jeremy began his IT career writing "Shadow IT" applications to automate his engineering documentation, then wandered into software development because it looked like more fun. Jeremy is the author of the open source StructureMap tool for Dependency Injection with .Net, StoryTeller for supercharged acceptance testing in .Net, and one of the principal developers behind FubuMVC. Jeremy's thoughts on all things software can be found at The Shade Tree Developer at http://codebetter.com/jeremymiller.
This entry was posted in Featured, StructureMap. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Jason Gill

    I was playing around with the code and came up with the following syntax:

    ExplicitTarget secondTarget = ObjectFactory
    .InstanceOf()
    .With(“name”).EqualTo(“Jason”)
    .With(theBlueProvider)
    .Create();

    So what do you think? If you like it I can send you my changes.

  • WardBell

    Good move. Closes a gap in standard ctor injection. Maybe, like Chris, I should give S&M a spin next time.

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    @Ben,

    That was partially for you too. FillDependencies() basically does the exact same thing.

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    @Rob,

    Yes, you certainly can use these together, and I’ve got a unit test to prove it. I wanted these exact features this morning so I could do:

    AddReportMenu(“Name of some report”).ThatLaunches();

    or:

    public void OpenTrade(string tradeId)
    {
    Trade trade = _tradeRepository.FindTrade(tradeId);
    IPresenter tradePresenter = ObjectFactory.With
    (trade).GetInstance
    ();
    navigateTo(tradePresenter);
    }

  • http://www.ayende.com/Blog/ Ayende Rahien

    Jeremy,
    Let us see, there are 3 major containers in the .NET world…
    All of them are OSS, so NDA doesn’t cover it.
    That leaves us with an announced container, from a place where you get to sign an NDA-a-minute….
    What _could_ you be talking about :-)

    Cool features, by the way.

  • http://www.bluespire.com/blogs Rob

    I can definitely use these new features. They simplify some scenarios I encountered on my last WPF application. The syntax looks good too. Can you use these features together as well? In other words, resolve a type that isn’t registered, providing some args and expecting the rest to come from the container.

  • http://www.chrisholmesonline.com Chris Holmes

    That’s does it. I’m using StructureMap in my side project…

  • http://www.flux88.com Ben Scheirman

    I like it. It makes total sense.

    I bet I can guess which “container” you mean. ;)