Fork me on GitHub

Replace or Clear Out Previous Registrations Edit on GitHub


Several members of the StructureMap team were also very active in a now semi-defunct web framework called FubuMVC that was built with quite a bit of extensibility in mind. One of the extensibility mechanisms that was successful in FubuMVC was the ability for applications or addon libraries to swap out the default services in the main StructureMap application container.

The approach we took for this extensibility was what I flippantly call the "Mongolian BBQ" architecture. The framework should take the application specific registrations, the framework defaults, and all the discovered addons and figure out how to order the registrations to enforce the following levels of registration precedence:

  1. The application specific registrations should always win out
  2. Package or extension specific overrides
  3. Default framework service registrations

To make this kind of modular and adaptive registration work, FubuMVC introduced a couple concepts that we've now pulled back into StructureMap:

  1. The Fallback Services introduced in the previous topic where you can make a registration that effectively tells StructureMap to "use this registration if nobody else tells you something differently".
  2. The new Registry.For().ClearAll() mechanism shown in this topic that tells StructureMap to "disregard what everyone else said to use".

Typically in FubuMVC, we would use fallback service registrations for most of the framework defaults and occasionally use the ClearAll() type mechanics down the line as an analogue to the CSS !important keyword to make a particular registration take precedence in the face of multiple registrations.

In usage, let's say that our application needs some type of IWidget service to run. For an important client, they want to deploy our system with a special version, so we will create a new StructureMap Registry to apply their specific registrations using the ClearAll() mechanism to insure that the important client gets their way:


public class ImportantClientWidget : IWidget { }

public class ImportantClientServices : Registry
{
    public ImportantClientServices()
    {
        For<IWidget>().ClearAll().Use<ImportantClientWidget>();
    }
}

In usage, the ClearAll() stomps all over the default registration before adding their own:


[Fact]
public void clear_all_in_action()
{
    var container = new Container(_ =>
    {
        _.For<IWidget>().Use<AWidget>();

        _.IncludeRegistry<ImportantClientServices>();
    });

    container.GetInstance<IWidget>()
        .ShouldBeOfType<ImportantClientWidget>();

    Debug.WriteLine(container.WhatDoIHave(pluginType: typeof(IWidget)));
}

If you were to check the WhatDoIHave() view for IWidget, you would see only the ImportantClientWidget:

==============================================================================================================================================
PluginType     Namespace                           Lifecycle     Description                                                         Name     
----------------------------------------------------------------------------------------------------------------------------------------------
IWidget        StructureMap.Testing.Acceptance     Transient     StructureMap.Testing.Acceptance.clear_all+ImportantClientWidget     (Default)
==============================================================================================================================================