Skip to content
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 Throwing InvalidOperationException in .NET 8 #94736

Closed
eajhnsn1 opened this issue Nov 14, 2023 · 7 comments
Closed

Comments

@eajhnsn1
Copy link

Description

After upgrading to .NET 8, ActivatorUtilties.CreateInstance is throwing InvalidOperationException when the following conditions are met

  1. The type being activated has multiple constructors, one of which is the default constructor
  2. There are no constructor parameters passed to ActivatorUtilties.CreateInstance, ie. Type.EmptyTypes

Reproduction Steps

    internal class Program
    {
        static void Main(string[] args)
        {
            _ = ActivatorUtilities.CreateInstance(new EmptyServiceProvider(), typeof(TestClass));
        }

        class TestClass
        {
            public TestClass()
            {
                    
            }
    
            /* Comment out this constructor and the call will succeed */
            public TestClass(int value)
            {

            }
        }

        class EmptyServiceProvider : IServiceProvider
        {
            public object? GetService(Type serviceType)
            {
                return null;
            }
        }
    }    

Expected behavior

Call the default constructor.

Actual behavior

Throwing InvalidOperationException, with message "Multiple constructors accepting all given argument types have been found in type ..."

Regression?

Yes this worked in .NET 7 and prior.

Known Workarounds

No response

Configuration

No response

Other information

No response

@dotnet-issue-labeler dotnet-issue-labeler bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Nov 14, 2023
@ghost ghost added the untriaged New issue has not been triaged by the area owner label Nov 14, 2023
@eajhnsn1 eajhnsn1 changed the title ActivatorUtilities.CreateInstance Throwing InvalidOperationException ActivatorUtilities.CreateInstance Throwing InvalidOperationException in .NET 8 Nov 14, 2023
@ghost
Copy link

ghost commented Nov 14, 2023

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

Issue Details

Description

After upgrading to .NET 8, ActivatorUtilties.CreateInstance is throwing InvalidOperationException when the following conditions are met

  1. The type being activated has multiple constructors, one of which is the default constructor
  2. There are no constructor parameters passed to ActivatorUtilties.CreateInstance, ie. Type.EmptyTypes

Reproduction Steps

    internal class Program
    {
        static void Main(string[] args)
        {
            _ = ActivatorUtilities.CreateInstance(new EmptyServiceProvider(), typeof(TestClass));
        }

        class TestClass
        {
            public TestClass()
            {
                    
            }
    
            /* Comment out this constructor and the call will succeed */
            public TestClass(int value)
            {

            }
        }

        class EmptyServiceProvider : IServiceProvider
        {
            public object? GetService(Type serviceType)
            {
                return null;
            }
        }
    }    

Expected behavior

Call the default constructor.

Actual behavior

Throwing InvalidOperationException, with message "Multiple constructors accepting all given argument types have been found in type ..."

Regression?

Yes this worked in .NET 7 and prior.

Known Workarounds

No response

Configuration

No response

Other information

No response

Author: eajhnsn1
Assignees: -
Labels:

untriaged, area-Extensions-DependencyInjection, needs-area-label

Milestone: -

@jkotas jkotas removed the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Nov 14, 2023
@mikechristiansenvae
Copy link

I believe you're supposed to be using ActivatorUtilitiesConstructorAttribute to indicate which constructor to use, if there is more than one.

Although it does seem that the behavior of this method was changed for .NET 8 in PR #75846

@eajhnsn1
Copy link
Author

I'll also add that this occurs when the container does not support using IServiceProviderIsService. The exception is being thrown from TryFindMatchingConstructor.

@buyaa-n
Copy link
Contributor

buyaa-n commented Nov 16, 2023

CC @steveharter

@steveharter steveharter self-assigned this Nov 16, 2023
@steveharter steveharter added this to the 9.0.0 milestone Nov 16, 2023
@ghost ghost removed the untriaged New issue has not been triaged by the area owner label Nov 16, 2023
@steveharter steveharter added the breaking-change Issue or PR that represents a breaking API or functional change over a prerelease. label Nov 16, 2023
@ghost ghost added the needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet label Nov 16, 2023
@ghost
Copy link

ghost commented Nov 16, 2023

Added needs-breaking-change-doc-created label because this issue has the breaking-change label.

  1. Create and link to this issue a matching issue in the dotnet/docs repo using the breaking change documentation template, then remove this needs-breaking-change-doc-created label.

Tagging @dotnet/compat for awareness of the breaking change.

@steveharter
Copy link
Member

steveharter commented Nov 16, 2023

Although it does seem that the behavior of this method was changed for .NET 8 in PR #75846

Correct; I verified this issue was due to the check\usage of IServiceProviderIsService in PR #75846.

Assuming we make no changes, the workarounds are:

  • The service provider must implement IServiceProviderIsService in order to tell whether or not a given parameter type is registered as a service.
  • Use [ActivatorUtilitiesConstructor] on the appropriate preferred constructor.

The original PR was marked with the breaking-change with the doc here: dotnet/docs#31785.

@steveharter steveharter added needs-further-triage Issue has been initially triaged, but needs deeper consideration or reconsideration and removed breaking-change Issue or PR that represents a breaking API or functional change over a prerelease. needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet needs-further-triage Issue has been initially triaged, but needs deeper consideration or reconsideration labels Nov 16, 2023
@steveharter
Copy link
Member

Closing as by design based on the breaking change notification linked above.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants