ipjohnson / Grace

Grace is a feature rich dependency injection container library
MIT License
336 stars 33 forks source link

Cannot resolve one dependency by open generic type #269

Closed davidkeaveny closed 3 years ago

davidkeaveny commented 4 years ago

Hi there,

I'm using Grace 7.1.1 with an ASP.NET Core 3.1 Web API, and am having a very weird problem with one specific dependency resolution that I hope someone can help with.

The API is resolving the following dependency:

public class AuthenticationQueryHandler : IQueryHandler<AuthenticationQuery, AuthenticationResult>
{
  private readonly ILoginService _logins;

  public AuthenticationQueryHandler(ILoginService logins) {
    _logins = logins;
  }

  public AuthenticationResult Handle(AuthenticationQuery query) {
    return _logins.Authenticate(query.Username, query.Password);
  }
}

The registrations are as follows:

var assemblies = Directory
  .GetFiles(AppDomain.CurrentDomain.BaseDirectory, "MyProject.*.dll")
  .Select(Assembly.LoadFile)
  .ToList();
register.ExportAssemblies(assemblies).BasedOn(typeof(IQueryHandler<,>)).ByInterfaces();

register.Export<LoginService>().As<ILoginService>();

When I try to resolve the AuthenticationQueryHandler using IQueryHandler<AuthenticationQuery, AuthenticationResult> then I get a LocateException on the logins parameter, saying that the ILoginService cannot be located. If I try to resolve the AuthenticationQueryHandler using AuthenticationQueryHandler then it resolves correctly. If I try to resolve ILoginService then it also resolves correctly, although it is also listed in the PossibleMissingDependencies.

Other implementations of IQueryHandler<,> resolve fine, so the registration process seems to be working okay.

davidkeaveny commented 4 years ago

I also just found that if I replaced the ILoginService dependency with an IServiceProvider then called (ILoginService)serviceProvider.GetService(typeof(ILoginService)) in my AuthenticationQueryHandler then the dependency would also fail to be resolved correctly; if I tried to resolve the explicit type then it works again, which I guess is a sort of work-around, but it's a bit of an anti-pattern.

So the issue appears to be that the dependency is not resolving properly when attempting to resolve the interface, but will resolve the type.

ipjohnson commented 4 years ago

Hi @davidkeaveny

That doesn't make much sense to me, I also agree passing in the IServiceProvider is not a good solution. Can you run call what do I have on the container after you've finished registering to see what's exported in the container?

ipjohnson commented 4 years ago

Where did you end up on this?

davidkeaveny commented 3 years ago

Sorry, I ended up switching to Autofac for this one, I was on a tight deadline.

ipjohnson commented 3 years ago

I’m going to close this out without a project to reproduce it