Fork me on GitHub

Lamar 2.0.0


Next

Inline Dependencies

Previous

Registration

ServiceRegistry DSL


Note! Lamar's ServiceRegistry is the equivalent to StructureMap's Registry, but the name was changed to disambiguate from the nearly infinite number of other Registry types in .Net.

Creating ServiceRegistry classes is the recommended way of using the Registry DSL.

The Registry DSL is mostly a fluent interface with some nested closure usage. The intent of the Registry DSL is to make the configuration process as error free as possible by using "compiler safe" expressions and defensive programming to point out missing data.

The ServiceRegistry Class

On all but the smallest systems, the main unit of configuration will probably be the ServiceRegistry class. Typically, you would subclass the ServiceRegistry class, then use the fluent interface methods exposed by the Registry class to create Container configuration. Here's a sample ServiceRegistry class below used to configure an instance of an IWidget interface:


public class PurpleRegistry : ServiceRegistry
{
    public PurpleRegistry()
    {
        For<IWidget>().Use<AWidget>();
    }
}

Including Other ServiceRegistry Objects

The next question is "how does my new ServiceRegistry class get used?"

When you set up a Container, you need to simply direct the Container to use the configuration in that ServiceRegistry class:


[Fact]
public void include_a_registry()
{
    var registry = new Registry();
    registry.IncludeRegistry<YellowBlueRegistry>();
    registry.IncludeRegistry<RedGreenRegistry>();
    registry.IncludeRegistry<PurpleRegistry>();
    // build a container
    var container = new Container(registry);
    // verify the default implementation and total registered implementations
    container.GetInstance<IWidget>().ShouldBeOfType<AWidget>();
    container.GetAllInstances<IWidget>().Count().ShouldBe(5);
}

Use versus Add

Note! This behavior changed from StructureMap. Lamar follows the now common approach mandated by ASP.Net Core that the last registration for a certain service type wins. So no more special meaning to Use() vs. Add().

There is no difference in behavior between Use and Add in Lamar. The two methods are synonyms and mostly remain in Lamar to provide and easier migration path from StructureMap. The

Registrations with For().Use()/Add()

To register an Instance of a type, the syntax is one of the Registry.For().Use() overloads shown below:


public class SettingDefaults : ServiceRegistry
{
    public SettingDefaults()
    {
        // If you know the plugin type and its a closed type
        // you can use this syntax
        For<IWidget>().Use<DefaultWidget>();

        // By Lambda
        For<IWidget>().Use(() => new DefaultWidget());

        // Pre-existing object
        For<IWidget>().Use(new AWidget());

        // This is rare now, but still valid
        For<IWidget>().Add<AWidget>().Named("A");
        For<IWidget>().Add<BWidget>().Named("B");
        For<IWidget>().Use("A"); // makes AWidget the default

        // Also rare, but you can supply an Instance object
        // yourself for special needs
        For<IWidget>().UseInstance(new MySpecialInstance());

        // If you're registering an open generic type
        // or you just have Type objects, use this syntax
        For(typeof (IService<>)).Use(typeof (Service<>));

        // This is occasionally useful for generic types
        For(typeof (IService<>)).Use(new MySpecialInstance());
    }
}

or


public class AdditionalRegistrations : ServiceRegistry
{
    public AdditionalRegistrations()
    {
        // If you know the plugin type and its a closed type
        // you can use this syntax
        For<IWidget>().Add<DefaultWidget>();

        // By Lambda
        For<IWidget>().Add(() => new DefaultWidget());

        // Pre-existing object
        For<IWidget>().Add(new AWidget());

        // Also rare, but you can supply an Instance object
        // yourself for special needs
        For<IWidget>().AddInstance(new MySpecialInstance());

        // If you're registering an open generic type
        // or you just have Type objects, use this syntax
        For(typeof(IService<>)).Add(typeof(Service<>));

        // This is occasionally useful for generic types
        For(typeof(IService<>)).Add(new MySpecialInstance());
    }
}

Add Many Registrations with For().AddInstances()

If you need to add several Instances to a single plugin type, the AddInstances() syntax shown below may be quicker and easier to use:



// registry is a StructureMap Registry object
registry.For<IService>().AddInstances(x =>
{
    // Equivalent to For<IService>().Add<ColorService>().....
    x.Type<ColorService>().Named("Red").Ctor<string>("color").Is("Red");

    // Equivalent to For<IService>().Add(new ColorService("Yellow"))......
    x.Object(new ColorService("Yellow")).Named("Yellow");

    // Equivalent to For<IService>().Use(() => new ColorService("Purple"))....
    x.ConstructedBy(() => new ColorService("Purple")).Named("Purple");

    x.Type<ColorService>().Named("Decorated").Ctor<string>("color").Is("Orange");
});

Named Instances

When you have multiple implementations of an interface, it can often be useful to name instances. To retrieve a specific implementation:


[Fact]
public void SimpleCaseWithNamedInstance()
{
    container = new Container(x => { x.For<IWidget>().Add<AWidget>().Named("MyInstance"); });
    // retrieve an instance by name
    var widget = (AWidget)container.GetInstance<IWidget>("MyInstance");
    widget.ShouldNotBeNull();
}

You can also register named instances with the following shorthand:


[Fact]
public void A_concrete_type_is_available_by_name_when_it_is_added_by_the_shorthand_mechanism()
{
    IContainer container = new Container(r => r.For<IAddTypes>().AddInstances(x =>
    {
        x.Type<RedAddTypes>().Named("Red");
        x.Type<GreenAddTypes>().Named("Green");
        x.Type<BlueAddTypes>().Named("Blue");
        x.Type<PurpleAddTypes>();
    }));
    // retrieve the instances by name
    container.GetInstance<IAddTypes>("Red").IsType<RedAddTypes>();
    container.GetInstance<IAddTypes>("Green").IsType<GreenAddTypes>();
    container.GetInstance<IAddTypes>("Blue").IsType<BlueAddTypes>();
}