2

Say I've a MVC Core Controller like this:

public class SomeController
{
     public SomeController(IConfiguration appConfig, Func<string> someDelegate)
     {
     }
}

Also, I'm using AutoFac to resolve injections. Object injections are working flawlessly while adding a delegate injection produces an ASP.NET Core exception which tells that Func<string> can't be injected because there's no component to inject with such type.

When I try to manually resolve SomeController using AutoFac I get the desired behavior.

Is there any way to support this scenario without using AutoFac to resolve controllers?

Matías Fidemraizer
  • 63,804
  • 18
  • 124
  • 206

2 Answers2

2

I was just run into this issue myself so I thought I would share for future reference as I had one case where I wanted to resolve a delegate but including an additional library seemed like overkill.

Given the following defintions:

public interface ISomething { /*...*/ };
public interface ISomeService { /*...*/ }

public class SomeService : ISomeService { /*...*/ }

public class Something
{
    public Something(ISomeService service, string key) { /*...*/ }
}

// I prefer using a delegate for readability but you
// don't have to use one
public delegate ISomething CreateSomething(string key);

The delegate can be registered like this:

var builder = services
    .AddSingleton<ISomeService, SomeService>()
    .AddTrasient<CreateSomething>(provider => key => new Something(provider.GetRequiredService<ISomeService>(), key));
karmasponge
  • 1,169
  • 2
  • 12
  • 26
1

Controllers are not resolved via DI by default, they are constructed in the DefaultControllerFactory or so.

Update

Microsoft.Extensions.DependencyInjection doesn't support named components, discovery, auto registrations, decorators etc.

It's meant to be simple out of the box IoC and provide the base for DI for basic applications and offer easy way for 3rd party IoC containers (with advanced features such as auto discovery, decorators etc.) to be integrated (basically all they need is process the information in IServiceCollection and return their own implementation of IServiceProvider from Configure method).

Tag helpers, controllers and view components are different in this aspect as they have their own activators (the default one use activation utilities, which at some point further down the pipeline use the service provider). For that reasons AddControllersAsServices exists, because it replaces DefaultControllerActivator (which uses ActivationUtilities, see DefaultControllerActivator.cs) with ServiceBasedActivator (which uses IServiceProvider, see ServiceBasedControllerActivator).

Also see this related answer for details on how to resolve controllers, tag helpers and view components via DI.

var builder = services
    .AddMvc()
    .AddControllersAsServices() // this one for your case
    .AddViewComponentsAsServices()
    .AddTagHelpersAsServices();
Community
  • 1
  • 1
Tseng
  • 61,549
  • 15
  • 193
  • 205
  • Thanks for the effort, but remember that my Q had this text: **Is there any way to support this scenario without using AutoFac to resolve controllers?** and, with the exception of injecting delegates into controllers' constructors, you don't need the `AddControllersAsServices` method. – Matías Fidemraizer Jul 21 '17 at 13:28
  • First, I don't know your registrations, so its even hard to tell what's wrong. Likely you use some `NamedParameter`, or only did a registration on services but not on Autofac or the other way around. `Func` is an odd delegate to be used, meaning it would always resolve one single string, since it's parameterless. Also what's the issue with adding `AddControllersAsServices()` – Tseng Jul 21 '17 at 13:57
  • Yeah, it's a named component. `Func` is a basic example. Actual case might be `Func<(string x, int y), Task>` – Matías Fidemraizer Jul 21 '17 at 15:35
  • Probably my Q&A should be marked as dup. I did some investigation during these hours and I found others asking similar issues. – Matías Fidemraizer Jul 21 '17 at 15:49
  • 1
    Well,`Microsoft.Extensions.DependencyInjection` doesn't support named components,discovery, auto registrations, decorators etc.It's meant to be simple and provide the base for DI for and easily for 3rd party IoC containers to be hooked in.Tag helpers, controllers and view components are different in this aspect as they have their own activators (the default one use activation utilities,which at some point use the service provider).For that reasons `AddControllersAsServices` exists (it replaces `DefaultControllerActivator` (ActivationUtilities) with `ServiceBasedActivator` (ServicerRovider) – Tseng Jul 21 '17 at 16:02
  • I see, I believe you should answer this instead, and I'll be able to mark yours as the right answer. – Matías Fidemraizer Jul 23 '17 at 11:20