-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ActivatorUtilities.CreateInstance is creating non-empty generic collections #109034
Comments
Tagging subscribers to this area: @dotnet/area-extensions-dependencyinjection |
If you want an empty list... why go through |
The ActivatorUtilities is being used in a serialization & deserialization context where many different types are involved, including system generic collections. We used to have a clean solution by using the it. |
@miguelnunes94 I believe the behavior difference you are seeing is not related to the target framework itself (.NET6 vs .NET8), but to the version of There has been a breaking change specifically around Regardless, I think your proposal is unreasonable however... if the team decided to pursue it, they would have to annotate all sorts of other constructors for various other collection and non-collection types to avoid picking copy constructors: it's just not feasible IMHO. To me, you are misusing this class if you are running into this problem, and I would suggest reconsidering your design instead. Perhaps if you wanted to expose a little bit more how/why you are using For instance, if you want to force MEDI to use a specific constructor when dealing with the raw services.AddTransient<List<int>>(_ => new List<int>()); Of course... the problem with that is that you would be forced to specify such an override for each specific T, as generic registrations don't have access to the underlying generic type for you to use in a generic factory. |
Correct. Related:
In v9, the ctor selected depends on the arguments but always respects the attribute Is there a reason why var collection = services.GetService<List<ITest>>(); that would just call the |
Thank you @julealgon and @steveharter for your comments! I understand that the difference in behavior is related to the breaking change mentioned (as described in the issue). However, it feels strange to see collections initialized with elements, and I'd like to get the team's opinion on this. I can provide more details on our use case, but I’d like to focus the discussion on the fact that, while After those changes, does it feel appropriate for a .NET initialization utility to return .NET collections pre-populated with elements? Details about our use caseIn brief, we have a large framework, widely used across numerous projects and clients, where domain entities and DTOs are represented by the same classes. The entities, which follow the active record pattern, access services through dependency injection. Since DTOs and entities share the same classes, and the entities require services, deserialization is handled by a contract resolver that supports dependency injection. However, not every type used in the DTOs is registered in the dependency injection container, which is where We often question this architecture, and a major refactoring is planned, but it will take several years to complete. In the meantime, business needs persist, and we continue to keep the framework updated to the latest .NET version. We can't use As a workaround during our upgrade to .NET 8, we added extra logic to the contract resolver. Based on certain rules, it can now selectively use either |
Description
Generic collections that have copy constructors (with
IEnumerable<T>
as parameter) are initialized with elements, when usingActivatorUtilities.CreateInstance
/ActivatorUtilities.GetServiceOrCreateInstance
.Reproduction Steps
Expected behavior
The
collection
object is an empty instance ofList
, becauseActivatorUtilities.CreateInstance
uses the constructorpublic List()
Actual behavior
The collection object is an instance of List containing two elements: one instance of
Test
and one ofTest2
. Currently,ActivatorUtilities.CreateInstance
is selecting the constructorpublic List(IEnumerable<T> collection)
.Regression?
We found this issue while upgrading from .Net 6 to .Net 8
Known Workarounds
No response
Configuration
.Net SDK 8.0.403
Other information
In such cases, the parameterless constructor may be preferable - particularly for generic collections with copy constructors. Consider annotating the expected constructors with the
ActivatorUtilitiesConstructorAttribute
to ensure the correct constructor is chosen.It should be related with:
The text was updated successfully, but these errors were encountered: