Using the Container Model

The queryable Container.Model is a power facility to look into your Lamar Container and even to eject previously built services from the Container. The Container.Model represents a static view of what a Container already has, and does not account for policies that may allow Lamar to validly discover types that it may encounter later at runtime.

Querying for Service Types

The WhatDoIHave() mechanism works by just iterating over the Container.Model.ServiceTypes collection as shown below:

container.Model.PluginTypes.Where(x => x.PluginType.Assembly == Assembly.GetExecutingAssembly())
    .Each(pluginType => Debug.WriteLine(pluginType.PluginType));

snippet source | anchor

Working with a Service Type

The IServiceFamilyConfiguration interface allows you to query and manipulate all the configured Instance's for a given service type.

See the entire IServiceFamilyConfiguration interface here.

Finding the Default for a Service Type

To simply find out what the default concrete type would be for a requested service type, use one of these two methods:

// Finding the concrete type of the default
// IDevice service
container.Model.DefaultTypeFor<IDevice>()
    .ShouldBe(typeof(DefaultDevice));

// Find the configuration model for the default
// IDevice service
container.Model.For<IDevice>().Default
    .ReturnedType.ShouldBe(typeof(DefaultDevice));

snippet source | anchor

Finding an Instance by Type and Name

Use this syntax to find information about an Instance in a given service type and name:

var redRule = container.Model.Find<Rule>("Red");

snippet source | anchor

All Instances for a Service Type

This sample shows how you could iterate or query over all the registered instances for a single service type:

container.Model.For<Rule>().Instances.Each(i =>
{
    Debug.WriteLine(i.Instance.Description);
});

snippet source | anchor

Testing for Registrations

To troubleshoot or automate testing of Container configuration, you can use code like the sample below to test for the presence of expected configurations:

// Is there a default instance for IDevice?
container.Model.HasDefaultImplementationFor<IDevice>().ShouldBeTrue();

// Are there any configured instances for IDevice?
container.Model.HasImplementationsFor<IDevice>().ShouldBeTrue();

snippet source | anchor

Finding all Possible Implementors of an Interface

Forget about what types are registered for whatever service types and consider this, what if you have an interface called IStartable that just denotes objects that will need to be activated after the container is bootstrapped?

If our interface is this below:

public interface IStartable : IDisposable
{
    void Start();
}

snippet source | anchor

public interface IStartable
{
    bool WasStarted { get; }

    void Start();
}

snippet source | anchor

public interface IStartable
{
    bool WasStarted { get; }

    void Start();
}

snippet source | anchor

We could walk through the entire Lamar model and find every registered instance that implements this interface, create each, and call the Start() method like in this code below:

var allStartables = container.Model.GetAllPossible<IStartable>();
allStartables.ToArray()
    .Each(x => x.Start());

snippet source | anchor

var allStartables = container.Model.GetAllPossible<IStartable>();
allStartables.ToArray()
    .Each(x => x.Start());

snippet source | anchor

I've also used this mechanism in automated testing to reach out to all singleton services that may have state to clear out their data between tests.