JasperFx / lamar

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

NullReferenceException in ServiceGraph.AllInstances() #340

Closed jwoodman510 closed 9 months ago

jwoodman510 commented 2 years ago

public IEnumerable<Instance> AllInstances() { return _families.Values.ToArray().SelectMany(x => x.All).ToArray(); }

NullReferenceException is thrown any time the above method is called when a value in _families.Values is null.

jeremydmiller commented 2 years ago

@jwoodman510 How did you configure the container to make that happen?

jwoodman510 commented 2 years ago

I've inherited a legacy codebase with some extremely large service registries, and said registries are used in tests. There is a test registry that removes some specific service registrations as some of the logic shouldn't run in the tests. There is one test written to assert that the test registry is removing the services as expected (this is where the exception is thrown).

e.g.

class ClassA {}
class ClassB {}
interface IGenericService<T> {}
class ServiceA : IGenericService<ClassA> {}
class ServiceB : IGenericService<ClassB> {}

class AppRegistry : ServiceRegistry
{
  // a huge number of nested registries and services here

  For<IGenericService<ClassA>>().Use<ServiceA>();
  For<IGenericService<ClassB>>().Use<ServiceB>();

  // a huge number of nested registries and services here
}

class TestRegistry : ServiceRegistry
{
  IncludeRegistry<AppRegistry>();

  RemoveAll(x => x.ServiceType == typeof(IGenericService<>);
}

// the "registry" test
void EnsureServicesAreNotRegistered()
{
  var container = new Container(x => x.IncludeRegistry<TestRegistry>());

  // Exception thrown here
  var hasRegistrations = container.Model.HasRegistrationsFor(typeof(IGenericService<>));

  Assert.False(hasRegistrations);
}