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

Better error message in ActivatorUtilities #43762

Merged
merged 1 commit into from
Jan 7, 2021

Conversation

jorisvergeer
Copy link
Contributor

The current error message gave me no pointers on what was/went wrong when I had an extra parameter to ActivatorUtilities.CreateInstance<SomeClass>(provider, usedParameter, unusedParameter). I experimentally found out that this causes issues.

Adding to the error message that all parameters have to be consumed would have saved me some time, and I hope that this change will save some time for a future developer.

Example that gave me unclear instructions:

        private interface IService
        {
            string Name { get; }
        }

        private class Service : IService
        {
            public string Name { get; set; }
        }

        private class MyClass
        {
            private readonly IService serviceA;
            private readonly IService serviceB;

            public MyClass(IService serviceA, IService serviceB)
            {
                this.serviceA = serviceA;
                this.serviceB = serviceB;
            }

            public void Print()
            {
                Console.WriteLine(serviceA.Name);
                Console.WriteLine(serviceB.Name);
            }
        }

        static void Main(string[] args)
        {
            var services = new ServiceCollection();
            services.AddSingleton<IService>(p => new Service { Name = "Injected" });

            var provider = services.BuildServiceProvider();

            var special = new Service { Name = "Special" };

            // The extra "Unused" string is not consumed by MyClass
            ActivatorUtilities.CreateInstance<MyClass>(provider, special, "Unused");

            // Throws: System.InvalidOperationException: 'A suitable constructor for type 'TestProject.Program+MyClass' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor.'
        }

@ghost
Copy link

ghost commented Jan 4, 2021

Tagging subscribers to this area: @eerhardt, @maryamariyan
See info in area-owners.md if you want to be subscribed.

Issue Details

The current error message gave me no pointers on what was/went wrong when I had an extra parameter to ActivatorUtilities.CreateInstance<SomeClass>(provider, usedParameter, unusedParameter). I experimentally found out that this causes issues.

Adding to the error message that all parameters have to be consumed would have saved me some time, and I hope that this change will save some time for a future developer.

Example that gave me unclear instructions:

        private interface IService
        {
            string Name { get; }
        }

        private class Service : IService
        {
            public string Name { get; set; }
        }

        private class MyClass
        {
            private readonly IService serviceA;
            private readonly IService serviceB;

            public MyClass(IService serviceA, IService serviceB)
            {
                this.serviceA = serviceA;
                this.serviceB = serviceB;
            }

            public void Print()
            {
                Console.WriteLine(serviceA.Name);
                Console.WriteLine(serviceB.Name);
            }
        }

        static void Main(string[] args)
        {
            var services = new ServiceCollection();
            services.AddSingleton<IService>(p => new Service { Name = "Injected" });

            var provider = services.BuildServiceProvider();

            var special = new Service { Name = "Special" };

            // The extra "Unused" string is not consumed by MyClass
            ActivatorUtilities.CreateInstance<MyClass>(provider, special, "Unused");

            // Throws: System.InvalidOperationException: 'A suitable constructor for type 'TestProject.Program+MyClass' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor.'
        }
Author: jorisvergeer
Assignees: -
Labels:

area-Extensions-DependencyInjection

Milestone: -

@jorisvergeer
Copy link
Contributor Author

@eerhardt that is better

@eerhardt
Copy link
Member

eerhardt commented Jan 4, 2021

@jorisvergeer - it looks like there are conflicts with your change. Can you address them?

The ActivatorUtilities.cs file has been moved to src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ActivatorUtilities.cs.

@jorisvergeer
Copy link
Contributor Author

@eerhardt Done

Copy link
Member

@eerhardt eerhardt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@eerhardt
Copy link
Member

eerhardt commented Jan 5, 2021

Looks like there is now a test failure. Can you fix it up?

@jorisvergeer
Copy link
Contributor Author

Oh damn.

I didn't think about that the tests would fail because a change in a error message. I kind of assumed that some tests were in a permanent state of failure except for private or release builds. (I've seen some of those setups).

I respect this level of unit tests.

@jorisvergeer
Copy link
Contributor Author

@eerhardt Lets see how this goes.
Couldn't run the tests locally.

@jorisvergeer
Copy link
Contributor Author

@eerhardt Shouldn't you have to approve this again after I change code?

@eerhardt
Copy link
Member

eerhardt commented Jan 5, 2021

The tests are still failing. The message appears duplicated here:

string? message = $"A suitable constructor for type '{instanceType}' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor.";

Looks like we will need to update that message as well.

@jorisvergeer
Copy link
Contributor Author

@eerhardt Took a while to get the tests running locally. It's passing now locally.

@eerhardt eerhardt merged commit 35e9354 into dotnet:master Jan 7, 2021
@ghost ghost locked as resolved and limited conversation to collaborators Feb 6, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants