dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.98k stars 4.66k forks source link

.NET Breaking Change - ActivatorUtilitiesConstructorAttribute doesn't work after upgrade to .NET 8 #95915

Closed darkthread closed 9 months ago

darkthread commented 9 months ago

Description

ActivatorUtilitiesConstructorAttribute can help ActivatorUtilities.CreateInstance() to choose the preferred constructor of mutilple-contructor type. It works fine in .NET 6/7, and failed in .NET 8.

Reproduction Steps

  1. dotnet new web -o net8-issue to create a empt web project.
  2. Change Program.cs content as following:
    
    var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(sp => ActivatorUtilities.CreateInstance(sp));

var app = builder.Build(); Console.WriteLine($".NET {Environment.Version}"); try { var scope = app.Services.CreateScope(); var svc = scope.ServiceProvider.GetRequiredService(); Console.WriteLine("MyService created successfully"); } catch (Exception ex) { Console.WriteLine("MyService failed to create"); Console.WriteLine(ex.Message); }

public class Foo { } public class Bar { } public class MyService { [ActivatorUtilitiesConstructor] public MyService(Foo foo, IWebHostEnvironment env) { } public MyService(Bar bar, IWebHostEnvironment env) { } }

3.  `dotnet run`

### Expected behavior

The output:

.NET 8.0.0 MyService created successfully


### Actual behavior

The output:

.NET 8.0.0 MyService failed to create Multiple constructors for type 'MyService' were found with length 2.


### Regression?

Change TargetFramework to net7.0, MyService is created successfully.

.NET 7.0.14 MyService created successfully



### Known Workarounds

Avoid using multiple constructors or other methods to create instance.

### Configuration

.NET 7.0.14, .NET 8.0.0, Microsoft Windows NT 10.0.22621.0 x64

### Other information

According to the [git commit](https://github.com/dotnet/runtime/commit/00937b28fe980944b694b17999dc61145ea6150a), Fix #91290 Improve perf of ActivatorUtilities.CreateInstance() change the logic in finding contructor and ignore ActivatorUtilitiesConstructorAttribute in first phase. 
ghost commented 9 months ago

Tagging subscribers to this area: @dotnet/area-extensions-dependencyinjection See info in area-owners.md if you want to be subscribed.

Issue Details
### Description ActivatorUtilitiesConstructorAttribute should help `ActivatorUtilities.CreateInstance()` to choose the preferred constructor of mutilple-contructor type. It works fine in .NET 6/7, and failed in .NET 8. ### Reproduction Steps 1. `dotnet new web -o net8-issue` to create a empt web project. 2. Change Program.cs content as following: ```cs var builder = WebApplication.CreateBuilder(args); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(sp => ActivatorUtilities.CreateInstance(sp)); var app = builder.Build(); Console.WriteLine($".NET {Environment.Version}"); try { var scope = app.Services.CreateScope(); var svc = scope.ServiceProvider.GetRequiredService(); Console.WriteLine("MyService created successfully"); } catch (Exception ex) { Console.WriteLine("MyService failed to create"); Console.WriteLine(ex.Message); } public class Foo { } public class Bar { } public class MyService { [ActivatorUtilitiesConstructor] public MyService(Foo foo, IWebHostEnvironment env) { } public MyService(Bar bar, IWebHostEnvironment env) { } } ``` 3. `dotnet run` ### Expected behavior The output: ``` .NET 8.0.0 MyService created successfully ``` ### Actual behavior The output: ``` .NET 8.0.0 MyService failed to create Multiple constructors for type 'MyService' were found with length 2. ``` ### Regression? Change TargetFramework to net7.0, MyService is created successfully. ``` .NET 7.0.14 MyService created successfully ``` ### Known Workarounds Avoid using multiple constructors or other methods to create instance. ### Configuration .NET 7.0.14, .NET 8.0.0, Microsoft Windows NT 10.0.22621.0 x64 ### Other information According to the [git commit](https://github.com/dotnet/runtime/commit/00937b28fe980944b694b17999dc61145ea6150a), Fix #91290 Improve perf of ActivatorUtilities.CreateInstance() change the logic in finding contructor and ignore ActivatorUtilitiesConstructorAttribute in first phase.
Author: darkthread
Assignees: -
Labels: `untriaged`, `area-Extensions-DependencyInjection`
Milestone: -
vcsjones commented 9 months ago

I believe this is a documented breaking change here https://learn.microsoft.com/dotnet/core/compatibility/extensions/8.0/activatorutilities-createinstance-behavior

And is further discussed in this issue https://github.com/dotnet/runtime/issues/94736

darkthread commented 9 months ago

I believe this is a documented breaking change here https://learn.microsoft.com/dotnet/core/compatibility/extensions/8.0/activatorutilities-createinstance-behavior

And is further discussed in this issue #94736

Thanks for the information. It seems that the breaking change has really rendered the ActivatorUtilitiesConstructorAttribute useless. It is suggested to include relevant explanations about ActivatorUtilitiesConstructorAttribute changes in the release notes and document to make the information more complete.