-
Notifications
You must be signed in to change notification settings - Fork 1.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
[Trimming] Fix event trigger trimming warnings #20810
[Trimming] Fix event trigger trimming warnings #20810
Conversation
…t-trigger-warnings
@@ -12,7 +12,7 @@ namespace Microsoft.Maui.Controls | |||
[ContentProperty("Actions")] | |||
public sealed class EventTrigger : TriggerBase | |||
{ | |||
static readonly MethodInfo s_handlerinfo = typeof(EventTrigger).GetRuntimeMethods().Single(mi => mi.Name == "OnEventTriggered" && mi.IsPublic == false); | |||
static readonly MethodInfo s_handlerinfo = typeof(EventTrigger).GetMethod(nameof(OnEventTriggered), BindingFlags.Instance | BindingFlags.NonPublic, binder: null, types: new Type[] { typeof(object), typeof(EventArgs) }, modifiers: null); |
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.
Could this instead be:
static readonly MethodInfo s_handlerinfo = typeof(EventTrigger).GetMethod(nameof(OnEventTriggered), BindingFlags.Instance | BindingFlags.NonPublic, binder: null, types: new Type[] { typeof(object), typeof(EventArgs) }, modifiers: null); | |
static readonly MethodInfo s_handlerinfo = new EventHandler(OnEventTriggered).Method; |
Then s_handlerinfo
can't be null (if we had NRT warnings in this file).
Would the OnEventTriggered
method still be preserved?
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.
That looks interesting, I haven't thought of that. I'll give it a try.
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.
So, it turns out we cannot do exactly what you suggested because OnEventTriggered
is an instance method, but I think we don't need the static s_handlerinfo
at all.
/cc @vitek-karas |
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.
But overall, if this solves a trimming warning, I think it is a step better than what we had before. 👍
_handlerdelegate = s_handlerinfo.CreateDelegate(_eventinfo.EventHandlerType, this); | ||
_handlerdelegate = ((EventHandler)OnEventTriggered).Method.CreateDelegate(_eventinfo.EventHandlerType, this); |
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.
Reading this class, trying to understand why so much System.Reflection usage in the original code...
I was wondering why it is not:
EventHandler _handlerdelegate;
//...
_handlerdelegate = OnEventTriggered;
But I guess what they are doing here is trying to make EventHandler<T>
of any type work?
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.
Yes, I had the same idea, but it didn't work with generic event handlers.
Agree with everything - not a fan of so much reflection, but this change should fix the trimming parts. |
@vitek-karas I don't get any AOT warnings related to The irony in this case is that we need to use |
@@ -71,7 +70,7 @@ void AttachHandlerTo(BindableObject bindable) | |||
try | |||
{ | |||
_eventinfo = bindable.GetType().GetRuntimeEvent(Event); | |||
_handlerdelegate = s_handlerinfo.CreateDelegate(_eventinfo.EventHandlerType, this); | |||
_handlerdelegate = ((EventHandler)OnEventTriggered).Method.CreateDelegate(_eventinfo.EventHandlerType, this); |
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.
@MichalStrehovsky I can't remember the rules around CreateDelegate
, is this something which might cause problems in AOT?
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.
This is fine for AOT. If we can invoke a method, we can also create a delegate to it with reflection.
Having to create a delegate just so we can get a MethodInfo
from it is unfortunate. Looks like this would benefit from a C# methodof
keyword or - since we're unlikely to get methodof
- dotnet/runtime#94975.
Description of Change
This PR fixes trimming warnings related to event triggers. Consider the following example:
An app with this markup will produce the following trimming warning:
The fix will preserve all public events on BindableObjects. This is not the optimal solution and we could consider adding a generic
EventTrigger<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents)] T>
variant ofEventTrigger
to preserve events only on types used with event triggers and improve app size.