hadashiA / VContainer

The extra fast, minimum code size, GC-free DI (Dependency Injection) library running on Unity Game Engine.
https://vcontainer.hadashikick.jp
MIT License
1.88k stars 163 forks source link

Attempting to Resolve a Closed Generic Concrete, when the Concrete isn't binded but a interface for it is, throws a Null Reference Exception #631

Open zadi0648 opened 6 months ago

zadi0648 commented 6 months ago

If you have this:

var theInterface = typeof(IMyGeneric<>);
var theConcrete = typeof(MyGeneric<>);
builder.Register(theConcrete, Lifetime.Singleton).As(theInterface);

This is fine: Resolver.Resolve<IMyGeneric<double>>();

But this, albeit will be erroneous anyways, will throw a null reference exception: Resolver.Resolve<MyGeneric<double>>();

Expected:

That a VContainerException is thrown instead, probably.

The Exception:

NullReferenceException: Object reference not set to an instance of an object VContainer.Internal.Registry.TryGetClosedGenericRegistration (System.Type interfaceType, System.Type openGenericType, System.Type[] typeParameters, VContainer.Registration& registration) (at C:/Git/VContainer0/VContainer/Assets/VContainer/Runtime/Registry.cs:125) VContainer.Internal.Registry.TryGet (System.Type interfaceType, VContainer.Registration& registration) (at C:/Git/VContainer0/VContainer/Assets/VContainer/Runtime/Registry.cs:112) VContainer.Container.Resolve (System.Type type) (at C:/Git/VContainer0/VContainer/Assets/VContainer/Runtime/Container.cs:199) VContainer.IObjectResolverExtensions.Resolve[T] (VContainer.IObjectResolver resolver) (at C:/Git/VContainer0/VContainer/Assets/VContainer/Runtime/IObjectResolverExtensions.cs:10)

Also:

Most IoC Containers would have API similar to something like this:

builder.Register(typeof(MyGeneric<>), typeof(IMyGeneric<>), Lifetime.Singleton);

The absence of a similar method within VContainer greatly confused me for some time, any chance it will be supported in the future? Or perhaps just a good example on how to bind a open generic interface to an open generic concrete, like at the top of this ticket, would have been very useful in the documentation.

mixedHans commented 5 months ago

You would need to register it like this:

builder.Register(theConcrete, Lifetime.Singleton)
      .As(theInterface)
      .AsSelf();builder.Register(theConcrete, Lifetime.Singleton)
      .As(theInterface)
      .AsSelf();

This way you also register theConcrete as itself, so you can resolve it.