
EDIT: October 30th, 2024: Nevermind, ServiceProvider is awful, Lamar is going to continue with a version 14 soon-ish.
If you’re not familiar with it, Lamar is an IoC/DI container for .NET. It was originally built to be a faster, modernized, ASP.Net Core-compliant replacement for the much older StructureMap IoC library and also as a necessary subsystem of what is now Wolverine.
First off, if you have a vested investment in continuing to use Lamar in your development environment, it’s going to be continued to be supported for the time being for any necessary bug fixes, performance issues, or the inevitable changes when Microsoft drops a new .NET release that breaks Lamar somehow. I don’t expect there to be any new feature development with Lamar other than that though.
I do want to start deprecating Lamar throughout the rest of the JasperFx / “Critter Stack” ecosystem though. First off, I think it’s increasingly untenable in the long run to maintain any custom IoC container tool in the .NET ecosystem as Microsoft continues to bake in new assumptions about capabilities and behavior directly into the .NET ServiceProvider (the new “keyed services” feature was done in a really weird way and I see that as a harbinger of yet more pain coming from our MS overlords). Second, we’ve had a few complaints about how Wolverine requires Lamar as its IoC container and silently replaces the built in container in your system. Not that many people really care, but the ones who do have been kind of nasty about it, so it’s just time for the Wolverine coupling to Lamar to go. Third — and I think this is going to be a very good thing in the long run for all of us — the community as a whole seems to be settling on mostly using the small subset of core IoC container behavior that’s exposed by the abstracted IServiceProvider interface and that’s largely making IoC tools a commodity.
At this point, I’ve ported Lamar’s type scanning and conventional service discovery to target the basic ServiceDescriptor model in the JasperFx.Core library that’s underneath both Marten and Wolverine. I think I’d like to see the command line diagnostics from Lamar ported to the build in DI container as part of Oakton, but not sure what the priority of that will be. Happy to have a volunteer for that one!
You might say that the type scanning thing sounds like Scrutor, but I’d say that it’s the other way around as the StructureMap type scanning predates Scrutor by many years.

On the way out, I’d like to run through some of the “special” features of both StructureMap and Lamar as a kind of wake for two projects I spent way too much time on over the years.
Passing Arguments at Runtime with StructureMap
For the most part, when you use an IoC container today you’re just letting it do what we used to call “auto-wiring” to use its configuration to figure out exactly what the full build plan is for a service and all its dependencies. But, StructureMap also let you go loose-y goose-y and pass in dependencies at runtime:
var widget = new BWidget();
var service = new BService();
var guyWithWidgetAndService = container
.With<IWidget>(widget)
.With<IService>(service)
.GetInstance<GuyWithWidgetAndService>();
In this case, StructureMap would build GuyWithWidgetAndService with all of its normal build plan, but substitute in the IWidget and IService value passed into the fluent interface above.
This feature was very flexible, endlessly vulnerable to permutations, and caused StructureMap to be less performant because of all of its runtime logic. I purposely ditched this with Lamar so that Lamar could “bake” in its build plans and pre-compile functions to build objects at runtime (I think basically every mainstream IoC tool you’d likely use in .NET does it this way now).
Inline Dependencies
Both Lamar and StructureMap allowed you to create service registrations that specified “inline” dependencies for only that service registration:
// ServiceRegistry is Lamar's analogue to IServiceCollection
// The For<T>().Use<TConcrete>() syntax is Lamar's older version
// of the AddSingleton<T>() extension methods used today
// with IServiceCollection
public class InlineCtorArgs : ServiceRegistry
{
public InlineCtorArgs()
{
// Defining args by type
For<IEventRule>().Use<SimpleRule>()
.Ctor<ICondition>().Is<Condition1>()
.Ctor<IAction>().Is<Action1>()
.Named("One");
// Pass the explicit values for dependencies
For<IEventRule>().Use<SimpleRule>()
.Ctor<ICondition>().Is(new Condition2())
.Ctor<IAction>().Is(new Action2())
.Named("Two");
}
}
Not something I’ve used myself in the recent past, but at one point this was relatively common. I used this to build rules engines with the “Event Condition Action” pattern.
Built In Environment Checks
Several containers now have diagnostics that allow you to verify the configuration by basically saying “do I know enough to build everything that is registered and is any implied dependencies missing?”. Lamar & StructureMap both did that with their diagnostics (which are more robust than the built in DI container, thank you), but a special little hook they have is built in environment checks as shown below:
public class DatabaseUsingService
{
private readonly DatabaseSettings _settings;
public DatabaseUsingService(DatabaseSettings settings)
{
_settings = settings;
}
[ValidationMethod]
public void Validate()
{
// For *now*, Lamar requires validate methods be synchronous
using (var conn = new SqlConnection(_settings.ConnectionString))
{
// If this blows up, the environment check fails:)
conn.Open();
}
}
}
That allowed you to do some additional runtime checking to verify a system was ready to work when container.AssertConfigurationIsValid(); is called. Just to show my age, this feature was originally added to probe whether or not required COM components were registered locally during deployment so that a deployment could “fail fast” and be quickly reverted.
DisposalLock because devs just can’t be trusted!
I bumped into this one just today. Let’s say that you have some naughty code in your system that is unintentionally trying to dispose the root container for your application (don’t laugh, it happened enough to spawn this feature). StructureMap/Lamar have a feature specifically for this problem that allows you to “lock” the disposal of the container to either find or stop the problem:
var container = Container.Empty();
// Ignore any calls to Container.Dispose()
container.DisposalLock = DisposalLock.Ignore;
// Throw an exception right here and now so we
// can find out who is erroneously disposing the container!
container.DisposalLock = DisposalLock.ThrowOnDispose;
// Normal mode
container.DisposalLock = DisposalLock.Unlocked;
container.Dispose();
Decorators and Interceptors
Lamar has a strong model for registering decorators or interceptors on service registrations to carry out some kind of action on a just build object or to wrap the inner behavior with a decorator.
public class WidgetDecorator : IWidget
{
public WidgetDecorator(IThing thing, IWidget inner)
{
Inner = inner;
}
public IWidget Inner { get; }
public void DoSomething()
{
// do something before
Inner.DoSomething();
// do something after
}
}
var container = new Container(_ =>
{
// This usage adds the WidgetHolder as a decorator
// on all IWidget registrations
_.For<IWidget>().DecorateAllWith<WidgetDecorator>();
// The AWidget type will be decorated w/
// WidgetHolder when you resolve it from the container
_.For<IWidget>().Use<AWidget>();
_.For<IThing>().Use<Thing>();
});
// Snippet of code from a unit test in the Lamar
// codebase
container.GetInstance<IWidget>()
.ShouldBeOfType<WidgetDecorator>()
.Inner.ShouldBeOfType<AWidget>();
This isn’t a feature I’ve personally used in years, but it was very common at one point. It’s also an awesome way for a team to bake in some magic behavior off to the side where folks won’t be able to find it easily later when the code misbehaves. At one point, I was absolutely ready to throttle very early MediatR users who abused the hell out of Lamar decorators as a middleware strategy and constantly asked me for help before MediatR got a usable middleware strategy.
Child Containers in StructureMap
Child Containers in StructureMap (or Profiles) were partially isolated containers that inherited service registrations (and singletons) from a root container and allowed you to make selected overrides of the parent containers.
Let’s just start by looking at this sample code:
[Fact]
public void show_a_child_container_in_action()
{
var parent = new Container(_ =>
{
_.For<IWidget>().Use<AWidget>();
_.For<IService>().Use<AService>();
});
// Create a child container and override the
// IService registration
var child = parent.CreateChildContainer();
child.Configure(_ =>
{
_.For<IService>().Use<ChildSpecialService>();
});
// The child container has a specific registration
// for IService, so use that one
child.GetInstance<IService>()
.ShouldBeOfType<ChildSpecialService>();
// The child container does not have any
// override of IWidget, so it uses its parent's
// configuration to resolve IWidget
child.GetInstance<IWidget>()
.ShouldBeOfType<AWidget>();
}
Sigh, folks loved this feature way back in the day. Especially for bigger, heavy client applications and sometimes for multi-tenancy. For me as a maintainer, it was a never ending nightmare to support because of all the possible permutations and how users would interpret the “proper” behavior differently. It also made StructureMap slow and more complex. I jettisoned this with Lamar to both optimize performance and to simplify my life.
There’s a very important lesson out of this feature and others in this page, the flexibility of a software tool and the performance characteristics of a software tool are often in conflict and there’s a tradeoff to be made.
Setter Injection
StructureMap and Lamar both supported Setter Injection where instead of only supplying dependencies through constructor functions, Lamar can also set dependencies on properties. There were various ways to do that, but the simplest (and ugliest) was through attributes:
public class Repository
{
// Adding the SetterProperty to a setter directs
// Lamar to use this property when
// constructing a Repository instance
[SetterProperty] public IDataProvider Provider { get; set; }
[SetterProperty] public bool ShouldCache { get; set; }
}
But you could also do it through policies:
public class ClassWithNamedProperties
{
public int Age { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public IGateway Gateway { get; set; }
public IService Service { get; set; }
}
[Fact]
public void specify_setter_policy_and_construct_an_object()
{
var theService = new ColorService("red");
var container = new Container(x =>
{
x.For<IService>().Use(theService);
x.For<IGateway>().Use<DefaultGateway>();
x.ForConcreteType<ClassWithNamedProperties>().Configure.Setter<int>().Is(5);
x.Policies.SetAllProperties(
policy => policy.WithAnyTypeFromNamespace("StructureMap.Testing.Widget3"));
});
var description = container.Model.For<ClassWithNamedProperties>().Default.DescribeBuildPlan();
Debug.WriteLine(description);
var target = container.GetInstance<ClassWithNamedProperties>();
target.Service.ShouldBeSameAs(theService);
target.Gateway.ShouldBeOfType<DefaultGateway>();
}
Now, this obviously sets up users for potential confusion about what properties are or are not being fulfilled by Lamar. I’m much more tolerant of a little “magic” in my code tools and I put a higher priority on “cleaner” looking code than I do on insisting that all code be explicit (and too ugly to actually read), but those “magic” tools absolutely have to be backed up with some kind of diagnostic that can unravel the “magic” behavior. Lamar actually has this now with its ability to preview the “build plan” for exactly how it’s going to resolve and build a service registration:
var container = new Container(x =>
{
x.For<IEngine>().Use<Hemi>().Named("The Hemi");
x.For<IEngine>().Add<VEight>().Singleton().Named("V8");
x.For<IEngine>().Add<FourFiftyFour>();
x.For<IEngine>().Add<StraightSix>().Scoped();
x.For<IEngine>().Add(c => new Rotary()).Named("Rotary");
x.For<IEngine>().Add(c => c.GetService<PluginElectric>());
x.For<IEngine>().Add(new InlineFour());
x.For<IEngine>().UseIfNone<VTwelve>();
});
// Little heavy weight, but this would show the equivalent C#
// code that would demonstrate what Lamar is doing to build
// or resolve every single service registration it has
Console.WriteLine(container.HowDoIBuild());
I’ve always been in the camp that says that setter injection is not ideal and that constructor injection (or method injection in newer frameworks like Wolverine or Minimal API), but there was from time to time a valid reason to use setter injection. Usually when there was some kind of inheritance involved — but that’s its own set of problems too.
Lamar’s diagnostics are head and shoulders better than the built in DI container from Microsoft and I think this will ultimately be the thing I miss most when Lamar is truly retired.
Overriding Services at Runtime
Lamar has some rump ability to do this, but StructureMap gave us the ultimate in runtime flexibility to override service registrations at will at runtime:
[Fact]
public void change_default_in_an_existing_container()
{
var container = new Container(x => { x.For<IFoo>().Use<AFoo>(); });
container.GetInstance<IFoo>().ShouldBeOfType<AFoo>();
// Now, change the container configuration
container.Configure(x => x.For<IFoo>().Use<BFoo>());
// The default of IFoo is now different
container.GetInstance<IFoo>().ShouldBeOfType<BFoo>();
// or use the Inject method that's just syntactical
// sugar for replacing the default of one type at a time
container.Inject<IFoo>(new CFoo());
container.GetInstance<IFoo>().ShouldBeOfType<CFoo>();
}
This was awesome for integration testing scenarios that depended on the IoC container in tests, but it was an unholy nightmare for me to maintain because it’s a permutation hell kind of trap. Yet again, Lamar chose performance and simplicity over flexibility and dropped this feature.
This is probably the one thing that people complain about the most switching from StructureMap to Lamar. I sympathize, but stand by my decisions there.
Missing Registration Policies
A lot of StructureMap was built in the days when Ruby on Rails seemed to be poised to dominate the development landscape, and I thought that Ruby’s missing method functionality looked cool as hell. StructureMap & Lamar both have a capability to “discover” or determine missing dependencies at runtime. While this was extensible, and we did use it on projects here and there, it was used internally by Lamar to “auto close” open generic types, find registrations for IEnumerable<T> by looking for T registrations, and some others.
The one Lamar/StructureMap feature (besides the diagnostics) I miss when using ServiceProvider is that Lamar can auto-resolve a concrete type upon request as long as Lamar can find all the necessary dependencies.
Lamar also has several policy types that would enable you to alter how registrations are actually built based on user defined policies like:
Use the “invoice” database connection string anytime the concrete type is in the namespace “OutApplication.Invoices”
Again, lots of opportunity for confusing the hell out of folks, and you’d absolutely want the magic unraveling diagnostics Lamar has in order to use something like that.
Summary
I’ve given up on several long running OSS projects in the 10-12 years with varying emotions of anger, disappointment, relief, or even a feeling of accomplishment. With Lamar I feel like it served its purpose in its time, and anyway:
“The world has moved on,’ we say… we’ve always said. But it’s moving on faster now. Something has happened to time.”
Roland Deschain
Love the gun slinger reference! Do you recommend just getting comfortable with the MS IoC or are there alternatives that continue to be supported you would recommend?
My PoV is that it’s inevitable that the community is just going to have to settle on the built in DI container