CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeremy D. Miller -- The Shade Tree Developer

Under the hood and working with .Net, TDD, Software Design, and Agile Stuff

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.



Comments

Ben Scheirman said:

I like it.  It makes total sense.

I bet I can guess which "container" you mean.  ;)

# January 23, 2008 11:51 AM

Chris Holmes said:

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

# January 23, 2008 12:12 PM

Rob said:

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.

# January 23, 2008 12:22 PM

Ayende Rahien said:

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.

# January 23, 2008 12:59 PM

Jeremy D. Miller said:

@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<SomePresenter>();

or:

public void OpenTrade(string tradeId)

{

 Trade trade = _tradeRepository.FindTrade(tradeId);

 IPresenter tradePresenter = ObjectFactory.With<Trade>(trade).GetInstance<TradePresenter>();

 navigateTo(tradePresenter);

}

# January 23, 2008 1:10 PM

Jeremy D. Miller said:

@Ben,

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

# January 23, 2008 1:11 PM

WardBell said:

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

# January 23, 2008 6:48 PM

Matthew Podwysocki's Blog said:

Scott Hanselman's recent post about the Daily Source Code 14 - Fluent Interface Edition got me to think

# February 1, 2008 5:50 PM

New StructureMap on the horizon : e-tobi.net said:

Pingback from  New StructureMap on the horizon : e-tobi.net

# February 12, 2008 10:38 AM

Jason Gill said:

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

ExplicitTarget secondTarget = ObjectFactory

 .InstanceOf<ExplicitTarget>()

   .With("name").EqualTo("Jason")

   .With<IProvider>(theBlueProvider)

 .Create();

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

# February 29, 2008 11:01 PM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add

About Jeremy D. Miller

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 previously worked as a systems architect building mission critical supply chain software for a Fortune 100 company and learned agile development practices as a .Net consultant at ThoughtWorks, one of the pioneers of agile development. Jeremy is the author of the open source StructureMap (http://structuremap.sourceforge.net) tool for Dependency Injection with .Net and the forthcoming StoryTeller (http://storyteller.tigris.org) tool for supercharged FIT testing in .Net. Jeremy's thoughts on just about everything software related can be found on his weblog "The Shade Tree Developer" at http://codebetter.com/blogs/jeremy.miller, part of the popular CodeBetter site. Jeremy is a Microsoft MVP for C#. Check out Devlicio.us!

This Blog

Syndication

News

All opinions expressed here constitute my (Jeremy D. Miller's) personal opinion, and do not necessarily represent the opinion of any other organization or person, including (but not limited to) my fellow employees, my employer, its clients or their agents.

About Me

"Best Of" Compendium

StructureMap (Dependency Injection for .Net)

StoryTeller (Supercharged Fit)

Build your own Cab

TestDriven

MVP