1

The auto-resolving of the .Net Core framework is not finding my registrations inside DryIoC.

This using the new .Net Core 2 framework, DryIoC 2.10.7 and DryIoc.Microsoft.DependencyInjection 1.2.2. I cannot update to DryIoC 2.11.7 because the DryIoc.Microsoft.DependencyInjection does not pick up the latest version. I did attempt to re-install the latter after the 2.11.7 install but that did not work (ambiguous references).

Here is my startup code:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
            .AddControllersAsServices();

    var container = new Container(rules => rules.With(propertiesAndFields: PropertiesAndFields.Auto))
                   .WithDependencyInjectionAdapter(services);
    container.ConfigureServiceProvider<CompositionRoot>();
}

And here are my registration code:

public CompositionRoot(IRegistrator registrator, IContainer container)
{
        //System Clock
        registrator.Register<IClock, ConcreteClock>(Reuse.Singleton, null, null, IfAlreadyRegistered.Keep);
        container.RegisterInstance<ISystemConfiguration>(new Configuration(container.Resolve<IClock>()), Reuse.Singleton, IfAlreadyRegistered.Keep);

        //Logging
        container.RegisterInstance<ILogging>(CreateLogger(container.Resolve<ISystemConfiguration>()), Reuse.Singleton, IfAlreadyRegistered.Keep);
}

Finally the controller:

public class AdminController : Controller
{
    private readonly ILogging _log;
    private readonly IClock _clock;
    public AdminController(ILogging log,
                           IClock clock)
    {
        _log = log;
        _clock = clock;
    }
}

Here is the exception:

System.InvalidOperationException: Unable to resolve service for type 'SharedAssets.Interfaces.ILogging' while attempting to activate 'DataDictionaryService.Controllers.AdminController'. at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, ISet1 callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(Type serviceType, Type implementationType, ISet1 callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, ISet1 callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(Type serviceType, ISet1 callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, ISet1 callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType, ServiceProvider serviceProvider) at System.Collections.Concurrent.ConcurrentDictionaryExtensions.GetOrAdd[TKey,TValue,TArg](ConcurrentDictionary2 dictionary, TKey key, Func`3 valueFactory, TArg arg) at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) at Microsoft.AspNetCore.Mvc.Controllers.ServiceBasedControllerActivator.Create(ControllerContext actionContext) at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.g__CreateController0(ControllerContext controllerContext) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__14.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__22.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context) at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__17.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__15.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Builder.RouterMiddleware.d__4.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware.d__7.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.d__7.MoveNext()

Thanks!

ChrisB
  • 13
  • 1
  • 4
  • Taking a look at an [example for DryIoC](https://bitbucket.org/dadhi/dryioc/src/8e609b011beafd71236f9cfe3bb2d3e0589e76ae/NetCore/src/DryIoc.AspNetCore.Sample/Startup.cs?at=default&fileviewer=file-view-default) you need to return the container. – DavidG Aug 17 '17 at 16:36
  • Thanks DavidG, I don't know how I missed that, because I looked at the same example. I guess these 12 hour days are starting to get to me... – ChrisB Aug 19 '17 at 08:21

1 Answers1

1

When using custom DI frameworks you need to update the ConfigureServices to return your custom IServiceProvider.

public IServiceProvider ConfigureServices(IServiceCollection services) {
    services.AddMvc()
            .AddControllersAsServices();

    var container = new Container(rules => rules.With(propertiesAndFields: PropertiesAndFields.Auto))
                   .WithDependencyInjectionAdapter(services);
    var provider = container.ConfigureServiceProvider<CompositionRoot>();
    return provider
}

At runtime, your provider will be used to resolve types and inject dependencies.

Reference: Introduction to Dependency Injection in ASP.NET Core: Replacing the default services container

Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • Thanks, Nkosi. However, after changing my code to follow your example, I now get a pretty obtuse StackOverflowException (the irony/coincidence, it is real...). An unhandled exception of type 'System.StackOverflowException' occurred in System.Private.CoreLib.dll From the memory graph in VS2017, it looks like DryIoC is causing overflow. – ChrisB Aug 18 '17 at 15:02
  • @ChrisB. That looks like signs of a circular dependency. Try creating a unit test. Setup the container and try to resolve one of your services. See if you get the same issue. If yes then you need to check your classes and see where you have the circular dependency. – Nkosi Aug 18 '17 at 15:24
  • Got it working. The rule added to the container is somehow causing the error. Even more strange, I have the the container self validating after doing all the registration and it does not throw the StackOverflowException on verification : "container.VerifyResolutions();" – ChrisB Aug 19 '17 at 09:19