Selecting the Constructor in StructureMap

I recently updated the StructureMap NuGet package in one of my projects to the latest version (3.1.5.154).  When I did this I was surprised when my code stopped compiling.  The code in question was code that specified which constructor to call on one of my dependencies.  Here is the old code that used to work just fine:

x.SelectConstructor<SessionGeneratorDefault>(() => new SessionGeneratorDefault((SecurityValues)null, false));
x.For<ISessionGenerator>().Use<SessionGeneratorDefault>()
             .Ctor<SecurityValues>("secValues").Is(Utilities._buildSecurityValues())
             .Ctor<bool>("forceLocalMode").Is(AppState._instance.ForceLocalMode);

After I updated the NuGet package I started getting a compile error:

StructureMap.ConfigurationExpression’ does not contain a definition for ‘SelectConstructor’ and no extension method ‘SelectConstructor’ accepting a first argument of type ‘StructureMap.ConfigurationExpression’ could be found (are you missing a using directive or an assembly reference?)

If you go an look at the StructureMap GitHub page for constructor selection it shows that the format has changed:

http://structuremap.github.io/registration/constructor-selection/

Which led me to the following code:

x.ForConcreteType<SessionGeneratorDefault>().Configure.SelectConstructor(() => new SessionGeneratorDefault((SecurityValues)null, false));
x.For<ISessionGenerator>().Use<SessionGeneratorDefault>()
             .Ctor<SecurityValues>("secValues").Is(Utilities._buildSecurityValues())
             .Ctor<bool>("forceLocalMode").Is(AppState._instance.ForceLocalMode);

Imagine my surprise when the code doesn’t work!  Oh, it compiled just fine, but at runtime it uses the incorrect constructor.

After a bit of trial and error I stumbled upon the fact that the “SelectConstructor” method is still available, it has just been moved in the object model.  So now the final code I came up with that works just fine is as follows (notice that it is all in one statement now as well instead of two):

x.For<ISessionGenerator>().Use<SessionGeneratorDefault>()
             .SelectConstructor(() => new SessionGeneratorDefault((SecurityValues)null, false))
             .Ctor<SecurityValues>().Is(Utilities._buildSecurityValues())
             .Ctor<bool>().Is(AppState._instance.ForceLocalMode)
             ;

*NOTE I removed the parameter names from the .Ctor methods (“secValues” and “forceLocalMode”) as they were not needed as the constructor did not have multiple parameters with the same Type.  But they could be added for clarity if desired.

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.