EDIT: 6/15/2018: Fixed an erroneous link and don’t you know it, there’s already a Lamar 1.0.2 up on Nuget (might take a second for indexing to catch up first) with some fixes to user reported problems.
Lamar is a new OSS library written in C# that is a new IoC container meant to replace the venerable, but increasingly creaky StructureMap library. Lamar is also Jasper‘s “special sauce” that provides runtime code generation and compilation that helps make Jasper’s runtime pipeline very efficient compared to its competitors. You can happily use the code generation and compilation without the IoC functionality. Thank you to Mark Warpool, Jordan Zaerr, Mark Wuhrith and many others for their help and early feedback.
I’m happy to announce that Lamar and Lamar.Microsoft.DependencyInjection (the ASP.Net Core adapter) were both published as v1.0.0 to Nuget this morning. It’s been beaten up a bit by early adopters and I finished off the last couple features around type scanning that I wanted for a v1 feature set, so here we go. I’m pretty serious about semantic versioning, so you can take this release as a statement that the public API signatures are stable. The documentation website is completely up to date with the v1 API and ready to go. If you’re kicking the tires on Lamar and run into any trouble, check out the Gitter room for Lamar.
To get going, check out Lamar’s Getting Started page.
Lamar as IoC Container
To get started, just add Lamar to your project through Nuget.
Most of the time you use an IoC container these days, it’s probably mostly hidden inside of some kind of application framework. However, if you wanted to use Lamar all by itself you would first bootstrap a Lamar container with all its service registrations something like this:
var container = new Container(x =>
{
// Using StructureMap style registrations
x.For<IClock>().Use<Clock>();
// Using ASP.Net Core DI style registrations
x.AddTransient<IClock, Clock>();
// and lots more services in all likelihood
});
Now, to resolve services from your container:
// StructureMap style
// Get a required service
var clock = container.GetInstance<IClock>();
// Try to resolve a service if it's registered
var service = container.TryGetInstance<IService>();
// ASP.Net Core style
var provider = (IServiceProvider)container;
// Get a required service
var clock2 = provider.GetRequiredService<IClock>();
// Try to resolve a service if it's registered
var service2 = provider.GetService<IService>();
Definitely note that the old StructureMap style of service resolution is semantically different than ASP.Net Core’s DI resolution methods. That’s been the cause of much user aggravation over the years.
Brief History of Lamar
I’ve become increasingly tired and frustrated with supporting StructureMap for the past several years. I also realized that StructureMap had fallen behind many other IoC tools in performance, and I really didn’t think that was going to be easy to address without some large scale structural changes in StructureMap.
Most of my ambition in OSS over the past couple years has been on Jasper (Marten was something we needed at work at the time and I had no idea it would turn out to be as successful as it has been). I’ve been planning for years to use Roslyn’s ability to generate code on the fly as a way to make Jasper’s runtime pipeline as fast as possible without losing much flexibility and extensibility. What is now Lamar’s code generation and compilation model was originally just a subsystem of Jasper for its runtime.
Because I was so focused on Jasper’s performance and throughput, I knew I would want to move beyond StructureMap as its IoC container. I tried the built in DI container from ASP.Net Core for a little bit, but its limited feature set was just too annoying.
Hence, Lamar was born as a new IoC container project called “‘BlueMilk” that would:
- Completely comply with ASP.Net Core’s requirements for IoC container behavior and functionality
- Retain quite a bit of functionality from StructureMap that I wanted
- Provide an “off ramp” for folks that depend on StructureMap today now that I’m wanting to stop support on StructureMap
- Ditch a lot of features from StructureMap that I never use personally and cause me a great deal of heartburn supporting
- Support Jasper’s “Special Sauce” code weaving
- Be as fast as possible
What’s Special about Lamar?
First off, how it works is unique compared to the at least 20-30 other OSS IoC containers in .Net. is the usage of dynamic generation of C# code at runtime and subsequent compilation via Roslyn in memory. Most other containers build and compile Expressions to Func
objects in memory. You might have to take my word for this, but that’s an awful model to work with efficiently.
Other containers depend on emitting IL and that’s just not something I ever care to do again.
It’s hard to explain, but when used in conjunction with Jasper, Lamar can in many cases use inline code generation to completely replace any kind of service location calls in Jasper’s runtime handling of messages or HTTP requests.
Why would I use this over the built in DI container?
Just to be clear, Lamar is completely compliant with all of ASP.Net Core’s DI behavioral rules and expectations. Lamar even directly implements several of the DI abstractions itself this time around rather than depending on adapter libraries that kinda, sorta force your IoC container to act like what the ASP.Net Core team arbitrarily decided was the new standard for everybody.
As you may already know, ASP.Net Core comes with a simplistic DI container out of the box and many teams are frankly going to be perfectly fine with that as it is. It’s fast and has a good cold start time.
All the same, I tried to live with the built in container as it was and got way too annoyed with all the features I missed from StructureMap, and hence, Lamar was born.
Lamar has a much richer feature set that I think absolutely has some significant value for productivity over the built in container including, but not limited to:
- Type Scanning Conventions
- Construction Policies
- Inline Dependencies
- Decorators
- Resolving Services by Type and Name
And for those of you hyperventilating because “oh my gosh, that sounds like some magic and [conference speaker/MVP/celebrity programmer] says that all code must be painfully explicit or the world is going to end!”, you’ll definitely want to check out all of Lamar’s diagnostic facilities that help you unravel problems and understand what’s going on within Lamar.
StructureMap to Lamar
Lamar supports a subset of StructureMap’s functionality and API. There are some behavioral differences to be aware of though:
- The lifetime support is simplified and reflects the ASP.Net Core semantics rather than the old StructureMap lifecycle support
- Registry is now
ServiceRegistry
- You can use a mix of StructureMap-style registration and ASP.Net Core style registrations natively
- There is no semantic difference between
Add()
andUse()
like there was in StructureMap. Last one in wins. Just like ASP.Net Core expects. - Lamar supports nested containers like most .Net frameworks expect, but child containers or profiles will probably not be supported
- Lamar doesn’t yet support setter injection (if you want it, just be prepared for an “I take pull requests” response)
- The Container.With().GetInstance() functionality is never going to be supported in Lamar. I’m theorizing that a formal auto-factory feature later will be a better alternative anyway
- Lamar only supports decorators for interception so far
Other Information:
Lamar was originally called “BlueMilk”
-
Roslyn Powered Code Weaving Middleware (a bit about how Jasper uses Lamar in its internals)
-
BlueMilk 0.8: It’s fast, runs MVC apps, and probably needs a new name
-
Introducing BlueMilk: StructureMap’s Replacement & Jasper’s Special Sauce