Skip to content

ActivatorUtilitiesConstructorAttribute Does Not Work in Some Cases #42339

@lawrence-laz

Description

@lawrence-laz

Describe the bug

ActivatorUtilities.CreateInstance<T>(IServiceProvider provider, params object[] parameters) does not respect ActivatorUtilitiesConstructorAttribute in a case when constructor ordering is changed.

To Reproduce

Steps to reproduce the behavior:

  1. Using version '3.1.6' of package 'Microsoft.Extensions.DependencyInjection'
  2. Run this test code:
    using Microsoft.Extensions.DependencyInjection;
    using System;
    using Xunit;
    
    namespace UnitTests
    {
        public class ActivatorUtilitiesConstructorTests
        {
            public class Dependency1 { }
            public class Dependency2 { }
            public class Dependency3 { }
    
            public class Service1
            {
                public Service1(Dependency1 dependency1, Dependency3 dependency3)
                {
                    throw new Exception("This should not be called.");
                }
    
                [ActivatorUtilitiesConstructor]
                public Service1(Dependency1 dependency1, Dependency2 dependency2, Dependency3 dependency3)
                {
                }
            }
    
            public class Service2
            {
                [ActivatorUtilitiesConstructor]
                public Service2(Dependency1 dependency1, Dependency2 dependency2, Dependency3 dependency3)
                {
                }
    
                public Service2(Dependency1 dependency1, Dependency3 dependency3)
                {
                    throw new Exception("This should not be called.");
                }
            }
    
            [Fact]
            public void CreateInstance_WithActivatorUtilitiesConstructorBeingSecond_ShouldChooseMarkedCtor()
            {
                // Arrange
                var dependency1 = new Dependency1();
                var dependency3 = new Dependency3();
    
                var provider = new ServiceCollection()
                    .AddScoped<Dependency2>()
                    .BuildServiceProvider();
    
                // Act & Assert
                ActivatorUtilities.CreateInstance<Service1>(provider, dependency1, dependency3); // This works.
            }
    
            [Fact]
            public void CreateInstance_WithActivatorUtilitiesConstructorBeingFirst_ShouldChooseMarkedCtor()
            {
                // Arrange
                var dependency1 = new Dependency1();
                var dependency3 = new Dependency3();
    
                var provider = new ServiceCollection()
                    .AddScoped<Dependency2>()
                    .BuildServiceProvider();
    
                // Act & Assert
                ActivatorUtilities.CreateInstance<Service2>(provider, dependency1, dependency3); // This fails.
            }
        }
    }
  3. See error This should not be called. when constructor marked with ActivatorUtilitiesConstructorAttribute is defined first, but no error when it is defined second.

Expected behavior

I expect ActivatorUtilitiesConstructorAttribute to be respected regardless of the order in which constructors were defined.

Additional context

The given example is reproduced using 3 dependencies. Removing one dependency makes both tests pass. Maybe this will help to get on a right path.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions