Description
Description
Current behavior
The effect of calling ActivatorUtilities.CreateInstance
methods (any of the overloads) depends on the order in which the constructors of the type being created are defined. The instance of the class is created if constructors are defined in one order, but the creation throws if constructors are defined in reversed order (see the code below).
Expected behavior
The call throws because it failed to disambiguate the appropriate constructor. This behavior will be in-line with the behavior of Activator.CreateInstance
.
Reproduction
using Microsoft.Extensions.DependencyInjection;
using static System.Console;
namespace AUCI
{
public class A { }
public class B { }
public class C { }
public class S { }
public class Creatable
{
public Creatable(
A a,
B b,
C c,
S s)
{
WriteLine("Creatable.Long");
}
public Creatable(
A a,
C c,
S s)
{
WriteLine("Creatable.Short");
}
}
public class Program
{
public static void Main(string[] args)
{
var services = new ServiceCollection();
services.AddScoped<S>();
using var provider = services.BuildServiceProvider();
var instance = ActivatorUtilities.CreateInstance(
provider,
typeof(Creatable),
// Please, note that the order of parameters does not match the order of constructors' arguments
new C(), new A());
}
}
}
The code above throws when invoking ActivatorUtilities.CreateInstance
, but works fine if we define the constructors in reversed order:
public class Creatable
{
public Creatable(
A a,
C c,
S s)
{
WriteLine("Creatable.Short");
}
public Creatable(
A a,
B b,
C c,
S s)
{
WriteLine("Creatable.Long");
}
}
It's counter-intuitive, IMHO.
Additional findings
I've looked through the implementation and debugged it:
- the first call to
ConstructorMatcher.Match
returns0
(meaning that the constructor is the worst possible match, the constructor does not match our parameters at all); - the second call to
ConstructorMatcher.Match
returns0
, so it's not better than the first one and we dismiss it; - we create the instance with the best match we've found (even knowing that it is ambiguous and does not match the parameters at all).
Configuration
The issue is not specific to configuration.
Regression?
Does not seem to be a regression.
Other information
It's probably a corner case, but it still would be great to remove the undefined (as I understand it) behavior.