Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Marten.StoreOptions.AutoRegister method throws Object reference not set to an instance of an object. #3644

Closed
pomianowski opened this issue Jan 31, 2025 · 1 comment

Comments

@pomianowski
Copy link
Contributor

pomianowski commented Jan 31, 2025

I have an application that can be simplified like this.

  • MyCompany.Orders - all source code
  • MyCompany.Orders.Worker - background tasks, RabbitMQ etc.
  • MyCompany.Orders.Api.Grpc - gRPC server for external actors

Both the worker and api use the same Marten code. Both make projections, both have the same documents. To simplify it, I configured the application as shown below, so that the generated code is in MyCompany.Orders:

        _ = services
            .AddMarten(options =>
            {
#if DEBUG
                // When in development mode, store generated code in the same assembly as the UnitOfWork
                // https://martendb.io/configuration/prebuilding
                options.SetApplicationProject(typeof(UnitOfWork).Assembly);
#else
                options.SetApplicationProject(typeof(UnitOfWork).Assembly, "/");
                options.GeneratedCodeMode = TypeLoadMode.Auto;
#endif
            })
            .AddAsyncDaemon(DaemonMode.HotCold)
#if DEBUG
            .OptimizeArtifactWorkflow(TypeLoadMode.Static)
#endif
            .UseLightweightSessions();

it more or less works, but it does not look elegant.

So I tried it this way:

        _ = services
            .AddMarten(options =>
            {
#if DEBUG
                // When in development mode, store generated code in the same assembly as the UnitOfWork
                // https://martendb.io/configuration/prebuilding
                options.SetApplicationProject(typeof(UnitOfWork).Assembly);
#else
                options.AutoRegister(scanner =>
                {
                    scanner.Assembly(typeof(UnitOfWork).Assembly);
                });
                options.GeneratedCodeMode = TypeLoadMode.Auto;
#endif
            })
            .AddAsyncDaemon(DaemonMode.HotCold)
#if DEBUG
            .OptimizeArtifactWorkflow(TypeLoadMode.Static)
#endif
            .UseLightweightSessions();

but in StoreOptions, the:
var assemblies = _assemblies.Union([options.ApplicationAssembly]).ToArray();
creates array of the provided typeof(UnitOfWork).Assembly assembly and null, because ApplicationAssembly is not set currently.

In my opinion, this can be solved in two ways, either add Assembly, to scan immediately, or omit it from the union and let the application work as before, but without adding application assembly if it has not yet been defined.

        internal void Scan(StoreOptions options)
        {
            options.ApplicationAssembly ??= System.Reflection.Assembly.GetEntryAssembly();

            var assemblies = _assemblies.Union([options.ApplicationAssembly]).ToArray();
            ...
        }

or

        internal void Scan(StoreOptions options)
        {
            var assemblies = options.ApplicationAssembly == null ? _assemblies : _assemblies.Union([options.ApplicationAssembly]).ToArray();
            ...
        }
@jeremydmiller
Copy link
Member

Closed by #3645

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants