Skip to content

[Breaking change]: ActivatorUtilities.CreateInstance behaves consistently independent of ctor definition order #31785

Closed
@maryamariyan

Description

@maryamariyan

Description

We introduced a breaking change in order to fix the bug with behavior dependence on order of constructor definition.

As part of this fix we also made the behavior of CreateInstance more coherent with CreateFactory, such that when IServiceProviderIsService is not present in the DI container then CreateInstance falls back to a CreateFactory logic, where only one constructor is allowed to match with all the required given input parameters.

In a more general case when we expect IServiceProviderIsService to be present, the CreateInstance API prefers the longest constructor overload that has all its arguments either available as input to the API or as registered in the container or available with default values to the constructor itself.

Example:

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

For the above class definition, with IServiceProviderIsService, the expectation is for ActivatorUtilities.CreateInstance<A>(serviceProvider, new C()) to instantiate A by picking the first constructor taking B, C and string.

Version

.NET 8 Preview 1

Previous behavior

ActivatorUtilities.CreateInstance had cases where it behaved unexpectedly.

The API would make sure all required instances passed to it exist in the constructor being picked. But the constructor selection was buggy and not reliable.

New behavior

General idea:

CreateInstance tries to find the longest constructor matching all parameters based on the behavior of IServiceProviderIsService.
If none are found, try to fallback to CreateFactory, if it finds more than one constructor it throws
if IServiceProviderIsService is not present it falls back to CreateFactory logic.
If IServiceProviderIsService is configured wrong, or does not exist, it is OK for the API to function incorrectly or ambiguously.

Type of breaking change

  • Binary incompatible: Existing binaries may encounter a breaking change in behavior, such as failure to load/execute or different run-time behavior.
  • Source incompatible: Source code may encounter a breaking change in behavior when targeting the new runtime/component/SDK, such as compile errors or different run-time behavior.

Reason for change

To fix the bug with inconsistent behavior when constructor overload definition order changes

Recommended action

Carefully examine constructor definitions if for the given instance type if you are suddenly getting failure now after updating to .NET 8 Preview 1. (Refer to new behavior above).

Feature area

C#, Core .NET libraries, Extensions

Affected APIs

ActivatorUtilities.CreateInstance

Fixed in PR dotnet/runtime#75846


Associated WorkItem - 60828

Metadata

Metadata

Assignees

Labels

🏁 Release: .NET 8Work items for the .NET 8 release📌 seQUESTeredIdentifies that an issue has been imported into Quest.breaking-changeIndicates a .NET Core breaking changesource incompatibleSource code may encounter a breaking change in behavior when targeting the new version.

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions