Appearance
Getting Started
This page does assume that you are already familiar with IoC containers. For more background on the concepts and usage of an IoC container within your application, see concepts
What is Lamar?
Lamar is a .NET library that provides two pieces of functionality:
- A fast Inversion of Control Container that natively supports the ASP.Net Core DI abstractions and a subset of the older StructureMap library
- The dynamic code generation and compilation features used underneath the IoC implementation
History and Motivation
StructureMap was the first production capable Inversion of Control container in the .Net ecosystem, with its first production usage in the summer of 2004. Despite its success, StructureMap's internals were not keeping up well with modern usage within ASP.Net Core applications and lagged in performance. Lamar was conceived as a replacement for StructureMap that would hugely improve upon StructureMap's performance, be completely compliant with the new ASP.Net Core DI behavior, and provide an easy off ramp for existing StructureMap users.
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:
cs
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:
cs
// 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.
Lamar within ASP.Net Core Applications
To use Lamar within ASP.Net Core applications, also install the Lamar.Microsoft.DependencyInjection library from Nuget to your ASP.Net Core project (and you can thank Microsoft for the clumsy naming convention, thank you).
With that NuGet installed, your normal ASP.Net Core bootstrapping changes just slightly. When you bootstrap your IWebHostBuilder
object that configures ASP.Net Core, you also need to call the UseLamar()
method as shown below:
cs
public static void Main(string[] args)
{
var builder = new WebHostBuilder();
builder
// Replaces the built in DI container
// with Lamar
.UseLamar()
// Normal ASP.Net Core bootstrapping
.UseUrls("http://localhost:5002")
.UseKestrel()
.UseStartup<Startup>();
builder.Start();
}
If you use a StartUp
class for extra configuration, your ConfigureContainer()
method can take in a ServiceRegistry
object from Lamar for service registrations in place of the ASP.Net Core IServiceCollection
interface as shown below:
cs
public class Startup
{
// Take in Lamar's ServiceRegistry instead of IServiceCollection
// as your argument, but fear not, it implements IServiceCollection
// as well
public void ConfigureContainer(ServiceRegistry services)
{
// Supports ASP.Net Core DI abstractions
services.AddMvc();
services.AddLogging();
// Also exposes Lamar specific registrations
// and functionality
services.Scan(s =>
{
s.TheCallingAssembly();
s.WithDefaultConventions();
});
}
public void Configure(IApplicationBuilder app)
{
app.UseMvc();
}
}
You can also still write ConfigureServices(IServiceCollection)
, but you'd miss out on most of Lamar's extra functionality beyond what that abstraction provides.
And that is that, you're ready to run your ASP.Net Core application with Lamar handling service resolution and object cleanup during your HTTP requests.
Lamar with ASP.NET Core Minimal Hosting
TIP
The [FromServices]
attribute is not necessary when using Lamar as the backing DI container behind Minimal API applications because Lamar implements the ASP.Net IServiceProviderIsService
interface.
Minimal hosting provides you with a condensed programming experience, only exposing the minimum required to get an ASP.NET Core application running. You can still use Lamar with the minimal hosting approach with the existing UseLamar()
extension methods to wire Lamar into the ASP.NET Core infrastructure. Follow the example below. You will still need the NuGet packages mentioned in the previous section.
cs
var builder = WebApplication.CreateBuilder(args);
// use Lamar as DI.
builder.Host.UseLamar((context, registry) =>
{
// register services using Lamar
registry.For<ITest>().Use<MyTest>();
// Add your own Lamar ServiceRegistry collections
// of registrations
registry.IncludeRegistry<MyRegistry>();
// discover MVC controllers -- this was problematic
// inside of the UseLamar() method, but is "fixed" in
// Lamar V8
registry.AddControllers();
});
var app = builder.Build();
app.MapControllers();
// Add Minimal API routes
app.MapGet("/", (ITest service) => service.SayHello());
app.Run();
TIP
Note, there are a couple overloads for UseLamar()
that may be more or less appropriate for your exact application's needs.
Lamar for Runtime Code Generation & Compilation
Please see compilation for more information.