Getting Instance by Type Name in StructureMap

Ever since we are using StructureMap we are also using this as a cheap replacement for Managed Extensibility Framework (MEF), as it allows us to scan arbitrary assembly paths for additional types to inject.
As we are also dealing with configuration sections where we specify which plugins or types we want to use in a specific environment, we are tasked with creating instances by their name – which is something StructureMap is not able to do out of the box.

However, with the help of an extension method it is very easy to fix this shortcoming. And here is how it goes.

In our example, we have a ConfigurationSection which is configured in our app.config like this:

<configuration>
  <configSections>
    <section 
      name="customConfigurationSection" 
      type="Net.Appclusive.Core.CustomConfigurationSection, Net.Appclusive.Core" 
      allowLocation="true" 
      allowDefinition="Everywhere" />
  </configSections>
  <customConfigurationSection 
    pluginTypeToBeLoaded="Net.Appclusive.Extensions.CustomPluginType" />
</configuration>

The accompanying ConfigurationSection class looks then like this:

public class CustomConfigurationSection : ConfigurationSection
{
  public const string SECTION_NAME = "customConfigurationSection";

  // ReSharper disable InconsistentNaming
  #pragma warning disable 649
  private static int pluginTypeToBeLoaded;
  #pragma warning restore 649
  // ReSharper restore InconsistentNaming

  [ConfigurationProperty(nameof(pluginTypeToBeLoaded), IsRequired = true)]
  public string PluginTypeToBeLoaded
  {
    get { return (string)this[nameof(pluginTypeToBeLoaded)]; }
    set { this[nameof(pluginTypeToBeLoaded)] = value; }
  }
}

Injecting this section is a simple For().Use() statement somewhere in our Registry setup:

For()
  .Use(() => (CustomConfigurationSection) ConfigurationManager
  .GetSection(CustomConfigurationSection.SECTION_NAME))
  .Singleton();

In order to make use of the type name referenced by the ConfigurationSection we can use the Model property inside our IContainer where all plugin types are available for inspection. We do this by defining an extension method with the name GetInstance that accepts a full qualified class name:

public static object GetInstance(this Container container, string typeName)
{
  var type = container.Model.PluginTypes
    .Select(e => e.PluginType)
    .FirstOrDefault(e => e.FullName == typeName);

  return container.GetInstance(type);
}

Now accessing this section and generating an instance from it is straightforward:

public class SomeClass
{
  private readonly Net.Appclusive.Extensions.CustomPluginType instance;

  public SomeClass(CustomConfigurationSection customConfigurationSection)
  {
    instance = (Net.Appclusive.Extensions.CustomPluginType) IoC.DefaultContainer
      .GetInstance(customConfigurationSection.PluginTypeToBeLoaded);
  }

  // ...
}

This is all it takes and now we are at the end of today’s post.

PS this is my first post created with StackEdit, so be gentle if I did not get it right the first time.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: