-
Notifications
You must be signed in to change notification settings - Fork 10k
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 needs to use the longest available constructor when multiple ctors are available #2871
Comments
From @NTaylorMullen on February 5, 2018 22:22 I'd think if we wanted to support multiple ctors we'd take an approach of decorating the constructor we'd want to use with some sort of attribute to say "Use this constructor when activating". Other DI systems do this already. Granted I think it'd be a bigger change outside of MVC if we were going to do this (don't think it's worth doing for just TagHelpers). |
@jbagga, what are the scenarios this would enable? |
From @rynowak on February 7, 2018 3:17 We have created a potential problem for our users everywhere that we use
This means that if you both:
Then you have a problem. This is particularly bad for tag helpers since we intend for it to be possible for someone to ship them as a library. This is also bad for everything else, since shipping those in libraries is a thing as well. property injection is the best injection IMO |
We just had a meeting about this and the solution we will go forward for ActivatorUtilities will be to take the only longest available public constructor for instantiation. |
This is now blocking a middleware fix. See #2915 |
@mkArtakMSFT / @muratg - if this is blocking @Tratcher 's work can you guys figure out how to get this on the priority list for preview2? |
Nice! As a workaround I ordered the constructors in the source code so that the first constructor is the one I want to be activated by DI. |
@Tratcher That bug was closed. What's the exact fix that was blocked? @pakrym @davidfowl Any thoughts on this? Are we picking up the first constructor currently? Would changing this be a breaking change? |
Test case: var serviceProvider = new ServiceCollection().AddSingleton<dep2>().BuildServiceProvider();
ActivatorUtilities.CreateInstance<test1>(serviceProvider, new object[] { new dep1() });
ActivatorUtilities.CreateInstance<test2>(serviceProvider, new object[] { new dep1() });
class dep1 { }
class dep2 { }
class test1
{
public test1(dep1 a) { } // this constructor is used
public test1(dep1 a, dep2 b) { }
}
class test2
{
public test2(dep1 a, dep2 b) { } // this constructor is used
public test2(dep1 a) { }
} |
I'll try the ordering workaround in Security but that wasn't working consistently in some UseMiddleware tests last night. |
There are two separate issues here that should be treated differently.
|
I think depending on the code path,
|
Found it: Re-ordering my constructors did work around the issue but is not a long term solution. |
Why do we have two completely different code paths for these methods? |
@pakrym you make it sound like we thought this type through 😄 |
HttpsRedirect and IIS middlewares also have multiple constructors, but they add local params rather than DI params so it appears to work. |
Triaging this in based on the discussions so far. |
From @mkArtakMSFT on February 12, 2018 18:48
From @jbagga on February 5, 2018 21:54
For cases that need a new constructor for a class (additional param), in order to avoid a breaking change we add an overload. However,
ActivatorUtilities
does not allow multiple applicable constructors.This restricts
TagHelpers
from changing the constructors.cc @rynowak
Copied from original issue: aspnet/Mvc#7330
Copied from original issue: aspnet/DependencyInjection#627
The text was updated successfully, but these errors were encountered: