Kicking off StructureMap 3

Actually, I started working hard on StructureMap 3.0 in the summer of 2010 but got badly derailed by other projects and a nasty bout of burnout.  I’m writing this post because I would dearly love to get community input and contributions and I’ve got folks contacting me that are chomping at the bit to start working on this. 

StructureMap was originally written in the summer of 2003 and revamped in the spring of 2004 for its very first release in June of that year.  Over the years it has had some significant rework (the 2.5 and 2.6 releases were both large changes), but at this point I firmly believe that the current 2.6.* internal structure is not worth improving.  Yes Virginia, I am opting to gut some of the internals of StructureMap in order to fix the most egregious problems and limitations of the current architecture and build a container that is good enough to last until we all give up on this silly .Net thing.  I’d also like to tear out any feature that I think is obsolete or just plain ugly to use and make StructureMap much leaner.

Nothing here is set in stone and feedback is very welcome.

 

My thoughts for 3.0:

My personal drivers for doing StructureMap3 are mostly to kill the nested container problems and get StructureMap ready to better handle multi-tenancy scenarios in a high volume FubuMVC application. I think that better Profile’s and/or the child container feature below would make multi-tenancy easier to achieve without killing the server’s memory usage.  Well, and I would like to make StructureMap easier to use for other peopleWinking smile  Making StructureMap the most used container in .Net or competing with the other hundred container tools to do every possible crazy scenario that folks can come up with is not on my agenda.

  • Remove the [Obsolete] methods
  • Better exception messages.  The error messages and the stacktraces really took a step backwards when I replaced the old Reflection.Emit code with dynamically generated Expression’s in the 2.6 release.  At a bare minimum, the stacktrace and exception messages need to be much cleaner and more accurately present what has gone wrong.
  • Better configuration diagnostics.  Completely taking a page out of FubuMVC and Bottles, I would like a StructureMap container to be able to tell you why and how it was configured the way it is.  Why did it select this constructure, why is this the default, where did this type come from.
  • Configuration model.  Today there is the configuration model (PluginGraph) and a runtime model (PipelineGraph and InstanceManager).  I would like to eliminate the separate models and make the configuration model much easier to consume by users.  From the lessons we learned with FubuMVC, I think the key to making the convention model far better is a very good semantic model that can be easily altered and read by both conventions and explicit configuration.  I think this is going to be the biggest change in the internals.
  • Far better convention support.  See the above feature.  Think of policies like “set the value of each constructor argument named ‘connectionString’ to this” or “make any Instance the singleton lifecycle where the concrete class name ends with ‘Cache’.”  We can do that kind of thing today with FubuMVC’s BehaviorGraph model.  I’d like to do the same with StructureMap.
  • Profiles.  I think we just flat our redo Profile’s from scratch and completely redesign that functionality from all new requirements. 
  • Runtime flexibility.  I would like to be able to allow users to register policies that could “teach” StructureMap how to resolve a requested type that it doesn’t know anything about.  I think we’d convert some of the hard coded rules in current StructureMap to this new pluggable strategy.  Think things like “this is a concrete type and I can resolve all of its dependencies, so I’ll just do it” or “this type closes an open generic type that I do know about” or “the name of this class ends in ‘Settings’ so I’ll use FubuCore’s ISettingsProvider to resolve it”
  • Better Lifecycle support.  A longtime limitation in StructureMap is that lifecycle can only be configured by the requested type, i.e., all instances of ISomething have to be the same lifecycle.  I’d like to eliminate that limitation.
  • Better support for modular configuration.  We already have the Registry model and I think it has worked out very well.  Most of the other IoC containers have implemented something similar by this point.  I’d like to extend the model to allow you to specify ordering rules between Registry classes and dependencies (hence, FubuCore’s dependency analysis functionality).  I would also like to add semantics to only add configuration if it is missing or conditional configuration.
  • Pluggable strategies for selecting constructor functions.  I don’t care for this one bit, but at least a couple prominent .Net OSS frameworks need this.
  • Nested containers.  I love this feature and its usability.  FubuMVC depends very heavily on this feature in StructureMap.  Its implementation, however, is horrific and there’s a nasty outstanding bug that I felt was too difficult to fix in 2.6.*.  I think we rewrite the nested container feature so that we have proper separation in scoping between the parent and nested container and avoid the need to do any copying/shuffling of the underlying configuration structure.
  • Child containers.  Not quite the same thing as nested containers.  This would be the ability to quickly clone an existing container and override the parent’s configuration.   
  • Eliminate the Xml configuration.  I have already ripped the Xml configuration support out of the core assembly in StructureMap 3.  I wouldn’t mind coming back and adding a subset of the existing Xml configuration back as an addon assembly and nuget.
  • Eliminate the old attribute configuration.  I had left this in there for years, but I’d never recommend to anyone that they use it.  I would like to consider just using the convention support to work against a subset of the same CLR attributes that MEF uses.
  • Full, living documentation.  I rewrote the documentation for the 2.5 release, but it wasn’t usable enough and quickly got out of date when 2.6 was released.  For 3.0 I’d like to use Sphinx for the documentation generation and host on http://readthedocs.org/ and make the documentation publish with pushes to Git.  Another heavy lesson learned is that the we need to strive to make the documentation organized around the tasks that a user would do instead of organized around StructureMap jargon.
  • Recipes.  This is where I really need community help the most.  I’d like to have some examples of integrating StructureMap into common .Net tools and frameworks.  I’m at a disadvantage because I’ve become very disconnected from mainstream .Net.  I have not used Entity Framework, WCF, Silverlight, Workflow Foundation, MEF, and barely used WPF, ASP.Net MVC, Prism, or WebForms.  I just don’t have enough visibility into those tools to help much.
  • Backwards Compatibility.  With a few exceptions, I think the registry DSL in StructureMap has settled into something usable.  I’d like to remove all the [Obsolete] methods and change a few things that seem to be confusing to use, but otherwise make it as easy as possible to upgrade from 2.6.* to 3.0.
  • No Silverlight support.  I have no intention of supporting Silverlight or any other mobile variant of .Net at this time.  I’m open to this happening later and I’m contemplating at least a version of StructureMap that is usable in the client profile.  This is an important decision to make soon-ish because I would like for StructureMap 3 to take a dependency on our FubuCore library and I don’t really want to care about the size of the assembly right now.
  • Fubu project portfolio.  I would like to fold StructureMap under the Fubu project family.  Part of that is branding, but it’s also community, the convenience of the GitHub organization model, and the common infrastructure that’s starting to grow up around documentation, Ripple, and the build support.
  • Use FubuCore.  There is quite a bit of overlap between the FubuCore library and what’s in the current codebase that I’d like to eliminate.  I’d also like to use FubuCore’s dependency graph support, the ObjectConverter, and integrate the SettingsProvider service out of the box for externalized configuration in StructureMap (here’s an explanation of an earlier version that’s still relevant).

 

Things I don’t plan on changing

  • The interception model.  By and large I think it’s been good enough for anything I’ve ever needed to do with it
  • The basic Registry DSL
  • Any of the methods on IContainer
  • Still don’t plan on adding AOP, but I’d like to have addon Nuget libraries for integrating existing AOP solutions with StructureMap someday

 

 

 

So why do this at all?

A couple months back I expressed some admiration for where one of the other IoC containers was going and that I was perfectly willing to forgo trying to compete with that particular tool (don’t even ask which one because I took a harder look at it and changed my mind).  He asked me why I didn’t just contribute the stuff I needed from StructureMap that was missing in that other container.  Fair question, but no, I’m not going to do that.  Why?  Because one of the best learning experiences you can possibly have as a developer is to take a hard problem that you’ve already solved and reflect on how you could solve that same problem in a much better way with all the things you’ve learned.  I’ve worked on and off on StructureMap for 8-9 years. I’ve rewritten some of the same subsystems in StructureMap a couple different times and even got a conference talk out of my experience called The Joys and Pains of a Long Lived Codebase at QCon – but I still think I will learn a great deal by going through with one last version of StructureMap.

49 thoughts on “Kicking off StructureMap 3

      1. I can’t speak to Maxime’s specific issue, obviously, but for me the API being out-of-sync with the documentation has been a significant barrier to usage/learning. I’m using StructureMap currently, but I have no idea if I’m doing it the “right” way.

        When I tried to follow the documentation for getting started, every method I used was marked with “Obsolete”. The recommended replacement methods didn’t have any documentation that I could find, and Googling “StructureMap new syntax” or related terms just seem to take me back to the online documentation.So yes, cleaning up the obsolete methods will improve the API dramatically. And so will the revised documentation.

        One of my favorite forms of documentation is the “Rhino Mocks Documented Via Unit Tests” example sheet that Jon Kreuger did (and Sharon Cichelli corrected). Not sure how this would translate to StructureMap, exactly, but in many cases an example is worth a thousand blog posts.

  1. Any chance the generics for Forward could be reversed? The current API is Forward (which reads correctly) but appears to do Foward… or I could be totally mistaken.

    Currently…

    .For().Use();
    .Forward();
    .Forward();

    Ie, ask for an IZ use X. But given the argument name of FROM I’d expect to have written

    .For().Use();
    .Forward();
    .Forward();

    1. Oh dude, I originally had the Forward API reversed and thought it was too confusing.

      Yes, I think we should revisit how the Forward thing is expressed. *I* can never remember how it works without jumping into the unit tests.

    2. Sorry, all the angle brackets were stripped… in VB…

      Currently…

      .For(Of IX).Use(Of X)()
      .Forward(Of IX, IY)()
      .Forward(Of IX, IY)()

      Expect it to be…

      .For(Of IX).Use(Of X)()
      .Forward(Of IY, IX)()
      .Forward(Of IZ, IX)()

  2. The current exception informational black hole is my main friction point with StructureMap. Fixing that would be unicorns and rainbows awesome.

    Diagnostics would help newbies learn what their configuration is producing and help experienced users avoid code/debug cycles spent parsing container.WhatDoIHave()

    -1 on Pluggable strategies for selecting constructor functions – Let them wrap their types with adapters if something like this is needed.

    Moving it under the Fubu brand seems a fine idea.

    Settings Provider (love it and use it everywhere) : Would love to have the ability for externally configured (Settings) objects to have a lifecycle which can be expired/reset by configuration file modifications. This would be useful for long running (services) where you want the configuration to be changeable without restarting.

    P.S. I like your new blog.

  3. I’d love to help set up the docs basics with Sphinx here too, so anything I can help with showing you and anyone else the ropes to Sphinx just let me know. That comes with the added bonus of hopefully getting more people knowledgeable about Sphinx and documentation so I can have some help with Fubu docs. 🙂

  4. Well, well, that’s what I call a backlog 🙂

    Forward has got to be either obvious or painful, depending on how your brain is wired. I certainly belong to the “always confused” camp, in an “IsAssignableFrom” kind of way.

    Personally, I would like to introduce capabilities geared towards use of the Func and Action types. Apart from the Func(Of T) that SM already provides, I also want support for Func(Of string, Of T) for named instances and Func(Of V, (Of string), Of T) for providing an argument to the “factory”.

    There is one MEF feature I kind of like because it can save you in some silly scenarios: A dependency can be satisfied by the property of some living object. I don’t know if there could be a SM-style way to pull this off. Maybe it would also pave the route to be able to register methods against Func and Action types, which can subsequently be used as dependency.

  5. Sounds great Jeremy.
    I think the Api is great, especially after the TheDefaultConcreteType syntax disappeared.

    Support for Lazy would be a feature as well, even though Func basically provides that functionality. Some more SetAllProperties conventions would be much appreciated also.

    Might be able to help out at some stage too.

    1. Definitely gonna do Lazy — even with Func I think Lazy is easier to use. That’s one of the scenarios I had in mind when I was writing about the “Runtime flexibility” above.

      SetAllProperties — I take pull requests;)

      I would dearly love to make this a real community project. I’m committed to making it easier for others to contribute. Yet another reason to do the near rewrite — I’d hate to expose innocent people to the current codebase.

  6. It’s great that you’ll continue working on StructureMap. About making examples of StructureMap integration with various parts of .NET – I would like to participate very much

  7. The DSL is great, no need to change that.

    The only thing that bugs me a lot is the discoverability of error messages, and configuration problems. A StructureMap exception 202 is not particularly helpful for newbies and even now I need to remind myself what half of them mean.

    A modular registration model and more convention based rules (auto-resolving “string connectionString”) would be pretty big wins too.

  8. I’m a long time user of SM. Waited for a long time for 3.0 and am very happy that you are getting back to it.

    I’d like to second the mwjacks0n on all the things he put on: Error messages, modular registration model, connectionString-specific resolution.

    One thing that also has been mentioned is related to documentation. It’s very hard to get new team members on board with it – the docs are outdated. SO and SM-mailing list are probably the only info source that my new team members can use (aside from studying the code that, as you said, could take some additional love). While we’re not using FubuMVC (for political reasons mostly), its code base is probably the most valuable asset for our new colleagues.

    Thanks!

  9. Glad to hear about the new version of SM! As for feedback:

    +1 on the better exception handling. It’s a real nightmare to deal with even if you’re very familiar with SM, but sheer “I’m just going to give up” insanity if you’ve never used it (biggest complaint I’ve heard from ppl).

    I’m probably the only one, but I’d really like Silverlight support as it would make doing some dynamic view/viewmodel stuff that we can do in WPF possible for some scenarios where we need to use Silverlight. Since 4/5 are on the current version of .NET it shouldn’t be too hard I hope :).

    1. Now I can understand why there is anyone that isn’t using StructureMap, in every single comparison of DI frameworks SM always comes out on top. But I’ve been using StructureMap since 2008 so I could see how a person that jumped in without that history and given the current state of docs would just say wtf and walk away.

      1. Well thanks for the vote of confidence, but even disregarding the issues with the terrible docs, *I* can think of lots of flaws with current StructureMap;-)

  10. I vote for doing SM 3 work under a new name. FubuSomething. I think it will provide more freedom to break compatibility. I think it would be a big help when handling support on StackOverflow or the mailing list to have that discriminator right up front to know what you’re dealing with.
    Its a whole new codebase, why not?

  11. I would like to see the Xml configuration remain an available option. Using Xml I can avoid hard references to assemblies within the project. I don’t like the idea of referencing dozens of assemblies in the project, just so StructureMap can be made aware of them. It introduces unnecessary dependencies.

    For example, we publish public interfaces that different software groups use to create class implementations. We drop their assemblies into a folder, add a reference in the Xml, and it’s done. Without Xml configuration, code has to change and a reference needs to be added into a project for initialization.

    Maybe there’s a better way to use assemblies without project references, but I’m unaware of it. If there there is a way, please let me know.

    Thanks

    1. First off, I think the Xml config does come back, but as an addon library/nuget. Ideally, I’d like the StructureMap.dll to be the client profile, with a fatter version for the web.

      You said: “I don’t like the idea of referencing dozens of assemblies in the project, just so StructureMap can be made aware of them”

      Just use the assembly scanning feature. You can even embed Registry classes in the external Xml for the registration. I don’t think there’s any reason to resort to Xml other than configuration items like connection strings that should never be in code — and I want to push folks to the AppSettingsProvider mechanism in FubuCore for that in greenfield work.

      This (http://structuremap.net/structuremap/ScanningAssemblies.htm) should show you how to do that.

      1. Am I the only one picking up a code smell from this? Scanning assemblies to populate the runtime interface-to-implementation mapping that is. A file scan is not very deterministic, even if you own all the assemblies in the folder. What happens when someone creates a new implementation of IFoo, but their mapping is overwritten because the original is scanned second? What if another team changes names on assemblies that deploy with your application? Could a scan return different resultant registries on a subsequent run, or in a different environment?

        On that note, I’m also not excited about convention- or heuristic-based mapping. All someone has to do to break that model is create a new class with a closer matching name than my class. This has the potential to exhibit some frustrating side effects, which could be very hard to track down in production.

        I realize a lot of projects are looking for alternatives to heavy-weight, explicit, file-based configuration. I just don’t want to see us trade in a serviceable inconvenience for a shiny new nightmare.

      2. @Scott,

        It’s a perfectly valid concern, and I think it’s a perfectly valid choice to opt for a completely explicit configuration model. In practice though, the convention based registration has worked out very well on many projects and all we’re doing here is pushing it farther. The explicit model certainly isn’t going away.

        * “All someone has to do to break that model is create a new class with a closer matching name than my class” — The conventions are much less fuzzy than that, or at least they are in StructureMap. Besides, you’ve got diagnostics to unravel that kind of thing and making those very diagnostics much more helpful is a major goal of SM3. Most of the time you use convention based registration you are just gathering up N number of implementations of an IFoo anyway.

        * You would never, ever just drop an assembly into production without running it through tests would you?

    1. @Stig,

      Jerry was my grandfather’s name, but I’ll be happy to answer here:

      1.) You *could* go run thru the IContainer.Model structure and figure out what has been created as an IDisposable transient during the nested container. Not really something I anticipated here.
      2.) For().Use() is destructive. Do For().Use() once to get the default, and a second call to For().Add() to get the 2nd registration. Look at the Xml comments for those 2 API calls.

    1. I think that’s going to be very possible and a touch easier in the new architecture, but we’ll just have to see. Can you add an issue to the GitHub repository for this? It’s the StructureMap3 repo off of the DarthFubuMVC organization.

  12. Jeremy,

    This is great news! I ALWAYS choose StructureMap when I can. The only times I couldn’t is due to the lack of Client Profile support when a project demanded it. That’s when I grab my second choice.

    I really like the idea of having the main assembly work with the Client Profile with an addon (fatter assembly) for the Web dependencies.

    Also, I’m glad to help with documentation, etc. for using SM with the standard .NET goodies (WPF, ASP.NET MVC). Although, I’m starting to dig into FubuMVC lately and would really like to just forget about WebForms and .NET MVC. Until then though, I’d help where I can.

  13. I would also like the “Better Lifecycle support” in combination with “Better configuration diagnostics”. E.g. it’s now possible to add a named instance with a different lifecycle, and StructureMap will not complain, but it also won’t work correctly.

    Additionally, having cleaner control over object lifetime would be nice. It’s not always convenient to pass around IContainers and right now cleaning up, say, thread locals (by calling new StructureMap.Pipeline.ThreadLocalStorageLifecycle().EjectAll()) seems a bit messy.

  14. Jeremy,

    I am quite new in this IoC and DI, but after following Rob Conery’s MVC1 video with you and researching on other DI tools like Munq, Funq, Autofac, etc. I found that your API and documentation are the best and very helpful to most developers like me. In fact, the performance reported is acceptable and opinionated. Your “Gentle Quick Start” is really helpful coz I am using class library for my DAL and reference it into my MVC. You DSL is simple to follow. You don’t have to write huge documentation to add for the existing ones. Giving code samples for many scenarios plus certain tips could be the best move. My chain of application is Database–>DAL(Petapoco/OrmLite)–>WCF Web API/ServicesStack–>ReadWriteEndPoints–>Clients(Asp.Net MVC Controller/Mobile MVC/JQuery/Dojo). Thanks for your attention.

  15. Sigh, I haven’t really started it yet. I’ve got volunteers out the wazoo, but I’m still the bottleneck. I will get to an interim StructureMap 2.7 release soon that might just specify most of the public API for 3.0. I’ll blog when something does happen.

  16. Hi there, very happy with the current SM, but there’s one thing that bothers me. Profiles, profiles doesn’t feel like something that’s a huge part of SM. Some features are missing in profiles. I think that you should always use profiles. Even if not used. That way we don’t have issues where the profile API differs from the normal API. Just a thought.

  17. Why isn’t there any date stamps on the posts?

    Is SM3 coming or not? When did JDM post his comment? 😉 would love to hear.

    UTC now: 2013-02-26 12:58:50.453

  18. Howdy! I could have sworn I’ve been to this web site before but after going through many of the articles I realized it’s new to me.
    Nonetheless, I’m certainly happy I stumbled upon it and I’ll
    be bookmarking it and checking back frequently!

  19. Hello,
    I am trying Strcuturemap 3.0 from NuGet, but found the doc from the official site to be out of date, Is there an updated doc I should use? some of the APIs using the scanner are no longer there (fore exmaple AssembliesFromPath…)

    1. Sigh, it’s still forthcoming. You can see what’s already there in the GitHub repo in the StructureMap.Docs project.

      AssembliesFromPath is an extension method in the StructureMap.Net4 assembly now. R# should be showing it to you with the CTRL-SHIFT-SPACE shortcut.

      – Jeremy

  20. Hi Jeremy,

    The new 3.0 version of StructureMap had removed some useful features from early version 2.6.*. I have known that you removed the XML configuration and also ObjectFactory.Inject method was no longer there. I think these features are very useful and I do not know why it doesn’t support on latest version. Is it possible you put it back :)? I can imagine it would hurt to keep these feature around since they are very useful for some cases. I am currently using version 2.6.4.1 and very happy with it. Again I love using StructureMap and thanks for developing it!

    1. @Xich,

      “Inject()” is still available on IContainer, so ObjectFactory.Container.Inject(). I was getting tired of trying to maintain the IContainer interface on the static ObjectFactory class as we added new capabilities and I’m trying to discourage folks from using ObjectFactory for anything other than a way to hang on to the application’s top level Container.Map

      As for the Xml configuration, it was going to be a near rewrite of the Xml configuration for StructureMap 3.0 and there wasn’t much demand for it. I’m happily open to pull requests if you want it for StructureMap 3.0, but it’s definitely going to be moved to a separate Nuget package because Xml support is not part of PCL.

      Thanks,

      Jeremy

Leave a comment