-
Notifications
You must be signed in to change notification settings - Fork 5k
Don't use Delegate.Method
in ServiceDescriptor
#114008
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
Conversation
The problem with this API is that in a trimmed app, accessing `Method` on a delegate type forces trimming to consider all delegate targets also targets of reflection (since we're grabbing a `MethodInfo` for whatever is the target). We do try to optimize this and only consider targets of the same delegate type, but in this case it means `Func<T, U>` and `Func<T,U,V>` which are very popular delegate types. Avoiding `Delegate.Method` is a 0.8% size saving for the Microsoft Store app. The differences are: * Originally this was calling `ToString` on the `MethodInfo`, which returns the name and signature of the method. I'm replacing this with `FullName` of the owning type and the name of the method. This is both more information and less information - we get owning type, we lose signature. It feels more useful nevertheless. * When the app is trimmed and `StackTraceSupport` feature switch is set to false, this will return question marks. The 0.8% size savings is present no matter the value of the `StackTraceSupport` switch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR updates ServiceDescriptor’s ToString implementation for service factories to avoid using Delegate.Method, reducing trimming impact and saving app size.
- Replaces calls to Delegate.Method.ToString with explicit formatting of the declaring type’s full name and method name.
- Uses conditional compilation (#if NET9_0_OR_GREATER) to support newer diagnostics while retaining legacy behavior.
@@ -262,7 +263,17 @@ public override string ToString() | |||
|
|||
if (KeyedImplementationFactory != null) | |||
{ | |||
return lifetime + $"{nameof(KeyedImplementationFactory)}: {KeyedImplementationFactory.Method}"; | |||
#if NET9_0_OR_GREATER |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic for retrieving and formatting method information for KeyedImplementationFactory is duplicated for ImplementationFactory. Consider refactoring this logic into a shared helper method to reduce duplication and improve maintainability.
Copilot uses AI. Check for mistakes.
@@ -276,7 +287,17 @@ public override string ToString() | |||
|
|||
if (ImplementationFactory != null) | |||
{ | |||
return lifetime + $"{nameof(ImplementationFactory)}: {ImplementationFactory.Method}"; | |||
#if NET9_0_OR_GREATER |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same method info retrieval logic is used here as for KeyedImplementationFactory. Refactoring this logic into a common helper can ensure consistency and reduce maintenance effort.
Copilot uses AI. Check for mistakes.
Tagging subscribers to this area: @dotnet/area-extensions-dependencyinjection |
Some test failures:
|
I've updated the tests to expect the new format, CI looks good now. |
The problem with this API is that in a trimmed app, accessing
Method
on a delegate type forces trimming to consider all delegate targets also targets of reflection (since we're grabbing aMethodInfo
for whatever is the target). We do try to optimize this and only consider targets of the same delegate type, but in this case it meansFunc<T, U>
andFunc<T,U,V>
which are very popular delegate types. AvoidingDelegate.Method
is a 0.8% size saving for the Microsoft Store app.The differences are:
ToString
on theMethodInfo
, which returns the name and signature of the method. I'm replacing this withFullName
of the owning type and the name of the method. This is both more information and less information - we get owning type, we lose signature. It feels more useful nevertheless.StackTraceSupport
feature switch is set to false, this will return question marks.The 0.8% size savings is present no matter the value of the
StackTraceSupport
switch.