JasperFx / lamar

Fast Inversion of Control Tool and Successor to StructureMap
https://jasperfx.github.io/lamar
MIT License
563 stars 118 forks source link

Globalization-Invariant mode not supported [.NET 6, Docker, Lamar 8.0.1] #353

Closed prodigy closed 1 year ago

prodigy commented 1 year ago

C# Version: 10.0 .NET: 6.0.9 Lamar: 8.0.1 Docker: mcr.microsoft.com/dotnet/aspnet:6.0-alpine

Description

Assume the following program. It's a simple, quite empty command line application with hosting, logging and lamar configured.

When running .NET 6 in an Alpine docker container, by default, the globalization invariant mode is active. You can read more about the topic here.

Program.cs

using Lamar;
using Lamar.Microsoft.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Events;
using Serilog.Settings.Configuration;

namespace MyApp;

public static class Program
{
    public static async Task<int> Main(string[] args)
    {
        Log.Logger = SetupDefaultLoggerConfiguration(new LoggerConfiguration()).CreateBootstrapLogger();
        try
        {
            return await CreateHostBuilder().RunCommandLineApplicationAsync<App>(args);
        }
        catch (Exception ex)
        {
            Log.Fatal(ex, "An error occurred: {Error}", ex.Message);
            return 1;
        }
        finally
        {
            Log.CloseAndFlush();
        }
    }

    private static void ConfigureApp(HostBuilderContext host, IConfigurationBuilder config)
    {
        config.AddJsonFile("appsettings.json", optional: true)
            .AddEnvironmentVariables();
    }

    private static void ConfigureContainer(HostBuilderContext host, ServiceRegistry services)
    {
        services.Scan(scan =>
        {
            scan.TheCallingAssembly();
            scan.WithDefaultConventions(ServiceLifetime.Transient);
        });
    }

    private static void ConfigureLogger(HostBuilderContext host, LoggerConfiguration config)
    {
        SetupDefaultLoggerConfiguration(config).ReadFrom.Configuration(host.Configuration, 
            nameof(Serilog),
            ConfigurationAssemblySource.UseLoadedAssemblies);
    }

    private static LoggerConfiguration SetupDefaultLoggerConfiguration(LoggerConfiguration configuration) =>
        configuration
            .MinimumLevel.Verbose()
            .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
            .Enrich.FromLogContext()
            .WriteTo.Console();

    private static IHostBuilder CreateHostBuilder() => new HostBuilder()
        .ConfigureAppConfiguration(ConfigureApp)
        .UseLamar(ConfigureContainer)
        .UseSerilog(ConfigureLogger);
}

Dockerfile

FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build

WORKDIR /app
COPY ./*.csproj /app/
RUN dotnet restore

FROM build as publish

WORKDIR /app
COPY . .
RUN dotnet publish . -c Release -o /app/.dist

FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine AS runtime

WORKDIR /app
COPY --from=publish /app/.dist /app/
ENTRYPOINT ["/app/rimago.admin"]

Expected Behaviour

The expected behaviour is, that the application runs as usual and successfully registers all services matching the assembly scanner.

Actual Behaviour

The application immediately crashes on assembly scanning. See the following stacktrace for more information:

Exception thrown: 'System.Globalization.CultureNotFoundException' in System.Private.CoreLib.dll
An exception of type 'System.Globalization.CultureNotFoundException' occurred in System.Private.CoreLib.dll but was not handled in user code: 'Only the invariant culture is supported in globalization-invariant mode. See https://aka.ms/GlobalizationInvariantMode for more information.'
Stack trace:
 >   at System.Globalization.CultureInfo..ctor(String name, Boolean useUserOverride)
 >   at BaselineTypeDiscovery.CallingAssembly.GetStackTraceInEnglish()
 >   at BaselineTypeDiscovery.CallingAssembly.Find()
 >   at Lamar.Scanning.Conventions.AssemblyScanner.TheCallingAssembly()
 >   at MyApp.Program.<>c.<ConfigureContainer>b__2_0(IAssemblyScanner scan) in C:\code\MyApp\Program.cs:line 42
 >   at Lamar.ServiceRegistry.Scan(Action`1 scan)
 >   at MyApp.Program.ConfigureContainer(HostBuilderContext host, ServiceRegistry services) in C:\code\MyApp\Program.cs:line 40
 >   at Lamar.Microsoft.DependencyInjection.HostBuilderExtensions.<>c__DisplayClass1_0.<UseLamar>b__0(HostBuilderContext context, IServiceCollection services)
 >   at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider()
 >   at Microsoft.Extensions.Hosting.HostBuilder.Build()
 >   at Microsoft.Extensions.Hosting.HostBuilderExtensions.<RunCommandLineApplicationAsync>d__1`1.MoveNext()
prodigy commented 1 year ago

Update: Moved to BaselineTypeDiscovery issues.