ActivatorUtilities.CreateInstance behaves consistently

The behavior of ActivatorUtilities.CreateInstance is now more consistent with CreateFactory(Type, Type[]). When IServiceProviderIsService isn't present in the dependency injection (DI) container, CreateInstance falls back to the CreateFactory(Type, Type[]) logic. In that logic, only one constructor is allowed to match with all the provided input parameters.

In the more general case when IServiceProviderIsService is present, the CreateInstance API prefers the longest constructor overload that has all its arguments available. The arguments can be input to the API, registered in the container, or available from default values in the constructor itself.

Consider the following class definition showing two constructors:

public class A
{
   A(B b, C c, string st = "default string") { }
   A() { }
}

For this class definition, and when IServiceProviderIsService is present, ActivatorUtilities.CreateInstance<A>(serviceProvider, new C()) instantiates A by picking the first constructor that takes B, C, and string.

Version introduced

.NET 8 Preview 1

Previous behavior

ActivatorUtilities.CreateInstance behaved unexpectedly in some cases. It made sure all required instances passed to it existed in the chosen constructor. However, the constructor selection was buggy and unreliable.

New behavior

CreateInstance tries to find the longest constructor that matches all parameters based on the behavior of IServiceProviderIsService.

Note

If IServiceProviderIsService is configured incorrectly or doesn't exist, CreateInstance may function incorrectly or ambiguously.

Type of breaking change

This change is a behavioral change.

Reason for change

This change was introduced to fix a bug where the behavior changed depending on the order of constructor overload definitions.

If your app starts behaving differently or throwing an exception after upgrading to .NET 8, carefully examine the constructor definitions for the affected instance type. Refer to the New behavior section.

Affected APIs

See also