Search code examples
c#dependency-injectionunity-containerconstructor-injection

Why does Unity fail to select a String constructor when resolving class?


I have upgraded Unity from v4.0.1 to v5.11.3 in a (.NET 4.5.2) project that worked fine before but since my upgrade I am getting the following exception: Resolution failed with error: Failed to select a constructor for System.String

The class I am trying to resolve has a String constructor and I have registered it with an InjectionConstructor. See code below:

// Multiple IDbContext registrations happen when the application is initialized
container.RegisterType<IDbContext, AuthenticationContext>(typeof(AuthenticationContext).ToString(), new InjectionConstructor(AppConstants.DatabaseKey));
container.RegisterType<IDbContext, ApplicationContext>(typeof(ApplicationContext).ToString(), new InjectionConstructor(AppConstants.DatabaseKey));

public class DbContextFactory : IDbContextFactory
{
   private readonly IUnityContainer _container;

   public DbContextFactory(IUnityContainer container)
   {
      _container = container;
   }

   public IDbContext CreateDbContext<TDbContext>() where TDbContext : IDbContext
   {
      var key = typeof(TDbContext).ToString();
      return container.Resolve<TDbContext>(key);
   }
}

public class AuthenticationContext : DbContextWrapper
{
   public AuthenticationContext(string connectionString) : base(connectionString)
   {
   }
}

public class DbContextWrapper : IDbContext
{
   public DbContextWrapper(string connectionString)
   {
   }
}

How should I interpret the exception? Failed to select a constructor for String, makes me think the registration was successful and that it is looking for a constructor that accepts a String but cannot find it? Which is strange because my AuthenticationContext only has one constructor which accepts... a string!

I tried clarifying a full code example on dotnetfiddle, but there I am getting an "Operation could destabilize the runtime" exception when initializing the UnityContainer. See https://dotnetfiddle.net/xuX57K


Solution

  • So the new exception message I got after enabling debug mode through container.EnableDebugDiagnostic(); got me thinking... It's saying I must configure the container to supply the string value for the constructor, of which I am sure I did. So that implies it is actually not even considering using my registration. When debugging the container registrations I saw my registration was there so that could not be the problem either.

    Then I realized that Unity registers all types by default so it was trying to create an instance of AuthenticationContext and hence it failed because when it uses an implicit registration it has no idea of what to do with the required string parameter.

    The error is in the DbContextFactory and this fixed it:

    public IDbContext CreateDbContext<TDbContext>() where TDbContext : IDbContext
    {
       var key = typeof(TDbContext).ToString();
    
       // This is wrong because it is trying to resolve AuthenticationContext for a given name.
       // But it should resolve a registration for IDbContext for that name since that is
       // how it was registered!
       // return container.Resolve<TDbContext>(key);
    
       return container.Resolve<IDbContext>(key);
    }