TL;DR — The latest Lamar V8.0.1 release has some bug fixes and mild breaking changes around the .Net Core DI integration that eliminates user reported problems with the new .Net 6 bootstrapping.
Hey, before I jump into the Lamar improvements for .Net 6, read Jimmy Bogard’s latest post for an example reason why you would opt to use Lamar over the built in DI container.
I’ve had a rash of error reports against Lamar when used with the new WebApplicationBuilder bootstrapping model that came with ASP.Net Core 6. Fortunately, the common culprit (in ahem oddball .Net Core mechanics more than Lamar itself) was relatively easy to find, and the most recent Lamar V8 made some minor adjustments to the .Net Core adapter code to fix the issues.
To use Lamar with the new .Net 6 bootstrapping model, you need to install the Lamar.Microsoft.DependencyInjection Nuget and use the UseLamar()
extension method on IHostBuilder
to opt into using Lamar in place of the built in DI container.
You can find more information about using Lamar with the new WebApplicationBuilder model and Minimal APIs in the Lamar documentation.
As an example, consider this simplistic system from the Lamar testing code:
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();
Notice that we’re adding service registrations directly within the nested lambda passed into the UseLamar()
method. In the previous versions of Lamar, those service registrations were completely isolated and additive to the service registrations in the Startup.ConfigureServices()
— and that was very rarely an issue. In the new .Net 6 model, that became problematic as some of Microsoft’s out of the box service registration extension methods like AddControllers()
depend on state being smuggled through the service collection and did not work inside of the UseLamar()
method before Lamar v8.
The simple “fix” in Lamar v8 was to ensure that the service registrations inside of UseLamar()
were done additively to the existing set of service registrations built up by the core .Net host building like so:
/// <summary>
/// Shortcut to replace the built in DI container with Lamar using service registrations
/// dependent upon the application's environment and configuration.
/// </summary>
/// <param name="builder"></param>
/// <param name="registry"></param>
/// <returns></returns>
public static IHostBuilder UseLamar(this IHostBuilder builder, Action<HostBuilderContext, ServiceRegistry> configure = null)
{
return builder
.UseServiceProviderFactory<ServiceRegistry>(new LamarServiceProviderFactory())
.UseServiceProviderFactory<IServiceCollection>(new LamarServiceProviderFactory())
.ConfigureServices((context, services) =>
{
var registry = new ServiceRegistry(services);
configure?.Invoke(context, registry);
// Hack-y, but this makes everything work as
// expected
services.Clear();
services.AddRange(registry);
#if NET6_0_OR_GREATER
// This enables the usage of implicit services in Minimal APIs
services.AddSingleton(s => (IServiceProviderIsService) s.GetRequiredService<IContainer>());
#endif
});
}
The downside of this “fix” was that I eliminated all other overloads of the UseLamar()
extension method that relied on custom Lamar ServiceRegistry
types. You can still use the IncludeRegistry<T>()
method to use custom ServiceRegistry
types though.
As always, if you have any issues with Lamar with or without ASP.Net Core, the Lamar Gitter room is the best and fastest way to ask questions.