ASP.NET Core Dependency Injection with Multiple Constructors

后端 未结 5 2055
独厮守ぢ
独厮守ぢ 2020-12-06 04:33

I have a tag helper with multiple constructors in my ASP.NET Core application. This causes the following error at runtime when ASP.NET 5 tries to resolve the type:

相关标签:
5条回答
  • 2020-12-06 04:40

    Illya is right: the built-in resolver doesn't support types exposing multiple constructors... but nothing prevents you from registering a delegate to support this scenario:

    services.AddScoped<IService>(provider => {
        var dependency = provider.GetRequiredService<IDependency>();
    
        // You can select the constructor you want here.
        return new Service(dependency, "my string parameter");
    });
    

    Note: support for multiple constructors was added in later versions, as indicated in the other answers. Now, the DI stack will happily choose the constructor with the most parameters it can resolve. For instance, if you have 2 constructors - one with 3 parameters pointing to services and another one with 4 - it will prefer the one with 4 parameters.

    0 讨论(0)
  • 2020-12-06 04:42

    ASP.NET Core 1.0 Answer

    The other answers are still true for parameter-less constructors i.e. if you have a class with a parameter-less constructor and a constructor with arguments, the exception in the question will be thrown.

    If you have two constructors with arguments, the behaviour is to use the first matching constructor where the parameters are known. You can look at the source code for the ConstructorMatcher class for details here.

    0 讨论(0)
  • 2020-12-06 04:45

    ASP.NET Core 2.1 and higher

    You can use ActivatorUtilitiesConstructorAttribute on the constructor which you want to be used in DI:

    [ActivatorUtilitiesConstructor]
    public MyClass(ICustomDependency d)
    {
    }
    
    0 讨论(0)
  • 2020-12-06 04:55

    ASP.NET Core Answer

    I've ended up with the following workaround until they fix/improve this.

    First, declare only one constructor in your controller (passing your required configuration settings only), considering that the settings objects passed in the constructor can be null (.NET Core will inject them automatically if you configure them in the Startup method):

    public class MyController : Controller
    {
        public IDependencyService Service { get; set; }
    
        public MyController(IOptions<MySettings> settings)
        {
            if (settings!= null && settings.Value != null)
            {
                Service = new DependencyServiceImpl(settings.Value);
            }
        }
    }
    

    Then, in your tests methods you can instantiate the controller in two ways:

    1. Mocking the IOptions object when you construct the tested object
    2. Construct passing null in all parameters and then Stub the dependency that you will use in your tests. Following you have an example:
    [TestClass]
        public class MyControllerTests
        {
            Service.Controllers.MyController controller;
            Mock<IDependencyService> _serviceStub;
    
            [TestInitialize]
            public void Initialize()
            {
                _serviceStub = new Mock<IDependencyService>();
                controller = new Service.Controllers.MyController(null);
                controller.Service = _serviceStub.Object;
            }
        }
    

    From this point you can have full testing with dependency injection and mocking ready in .NET Core.

    Hope it helps

    0 讨论(0)
  • 2020-12-06 04:59

    Answer is no. ASP.NET 5 DI doesn't support types with multiple public constuctors.

    Dependency Injection in ASP.NET Core (vNext)

    Dependency Injection in ASP.NET vNext

    0 讨论(0)
提交回复
热议问题