Skip to content

Automatic registration of open generics can lead to failures #309

@jods4

Description

@jods4

(I'm creating this issue as a reference for other users that may encounter this. I always disable auto-registration, so I am in no need for a fix or change.)

There are some edge cases where the default configuration of Grace can fail whereas MS DI works.
I will illustrate this with the popular MassTransit library, that just works with MS but fails to start in Grace default configuration.

The problem

The failure happens when MassTransit tries to locate the following service:

services.GetRequiredService(typeof(IEnumerable<Bind<IBus, IBusInstanceSpecification>>));

The catch is that in its basic default configuration, MassTransit does not register a Bind<IBus, IBusInstanceSpecification>>. The call above is expected to return an empty enumerable, which is how it works with MS DI.

This fails with the default Grace configuration, because of the following unfortunate sequence of events:

  • Grace will look for injectable Bind<IBus, IBusInstanceSpecification>;
  • As neither the open generic, nor that specific combination, has been registered, Grace will register it itself;
  • Now Grace tries to instantiate one Bind<IBus, IBusInstanceSpecification> but its ctor takes one IBusInstanceSpecification;
  • As this service is an interface and is not registered, Grace fails with LocateException.

Work-arounds

Disabling auto-registration is one solution: UseGrace(new InjectionScopeConfiguration { AutoRegisterUnknown = false }).

If auto-registration is desirable, then config.ExcludeTypeFromAutoRegistration(pattern) can be used to selectively disable it and accepts wildcards. In the scenario above, it would be advisable to disable auto-registraton of MassTransit.*.

Possible fixes in Grace

Maybe things could be changed to work out of the box with Grace?

Even with GetRequiredServices(), when locating an IEnumerable, failure to locate services may not be an issue, as an empty IEnumerable is an acceptable result.

Now, Grace should be careful to not swallow meaningful exceptions, e.g. when a service is registered (explicitly) but its dependencies can't be satisfied.

It might be a little tricky to code, but I would say somehow Grace should not auto-register a dependency that it then cannot satisfy.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions