Skip to content

[net11.0] Use ElementHandlerAttribute instead of DI for built-in visual elements#32862

Merged
simonrozsival merged 6 commits intodev/simonrozsival/net10.0-use-element-handler-attributesfrom
copilot/sub-pr-29952-again
Nov 26, 2025
Merged

[net11.0] Use ElementHandlerAttribute instead of DI for built-in visual elements#32862
simonrozsival merged 6 commits intodev/simonrozsival/net10.0-use-element-handler-attributesfrom
copilot/sub-pr-29952-again

Conversation

Copy link
Contributor

Copilot AI commented Nov 25, 2025

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Description of Change

Follow-up to #28357. Migrates ~80 built-in controls from DI registration to [ElementHandler(typeof(THandler))] attribute-based resolution.

Core changes:

  • All built-in controls now declare their handler via [ElementHandler(typeof(THandler))] attribute
  • Removed AppHostBuilderExtensions.AddControlsHandlers() bulk registrations
  • Added [ElementHandlerWithAndroidContext<THandler>] + IElementHandlerWithAndroidContext<THandler> for Android handlers requiring Context injection (FrameRenderer, ListViewRenderer, TableViewRenderer)
  • Updated MauiHandlersFactory resolution order: exact DI match → ElementHandlerAttribute → inherited DI match
  • Added IsCssEnabledByDefault runtime feature switch for CSS trimmability
  • Changed ElementHandlerAttribute from generic <THandler> to constructor parameter (Type handlerType) with [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] annotation for proper trimming support
  • Uses Activator.CreateInstance for handler instantiation with minimal IL2026 suppressions where needed

Example usage:

[ElementHandler(typeof(BorderHandler))]
public class Border : View, IContentView, IBorderView { }

// Platform-specific handlers
#if IOS || MACCATALYST
[ElementHandler(typeof(CollectionViewHandler2))]
#else
[ElementHandler(typeof(CollectionViewHandler))]
#endif
public class CollectionView : ReorderableItemsView { }

What's not yet converted:

  • IContentView handler registration (interfaces can't have attributes)
  • IElementHandlerWithAndroidContext<T> is internal—needs public API review if customers need it

Issues Fixed

Fixes #29952


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
Copilot AI changed the title [WIP] Use ElementHandlerAttribute for built-in visual elements [net10.0] Use ElementHandlerAttribute instead of DI for built-in visual elements Nov 25, 2025
Copilot AI requested a review from simonrozsival November 25, 2025 16:52
@simonrozsival
Copy link
Member

@copilot I was thinking about changing ElementHandlerAttribute<T> to ElementHandlerAttribute(Type handlerType) to simplify things (the new() constraint is using reflection internally anyway). Make sure to annotate the type with [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] to avoid any trimming warnings. The only type which will need to keep the generic type argument is ElementHandlerWithAndroidContextAttribute, but that's OK.

Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Nov 25, 2025

@copilot I was thinking about changing ElementHandlerAttribute<T> to ElementHandlerAttribute(Type handlerType) to simplify things (the new() constraint is using reflection internally anyway). Ma...

Changed in c9486dc. Now using [ElementHandler(typeof(SomeHandler))] syntax with [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] on the Type parameter. ElementHandlerWithAndroidContextAttribute<THandler> remains generic as you suggested.

@simonrozsival
Copy link
Member

@copilot I don't see changes to the attribute itself? Implement those. Also, remove unnecessary comment changes and suppression attributes.

Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Nov 26, 2025

@copilot I don't see changes to the attribute itself? Implement those. Also, remove unnecessary comment changes and suppression attributes.

Removed unnecessary suppression attributes and simplified in a4914e1. The attribute changes from c9486dc are there (changed from generic ElementHandlerAttribute<THandler> to constructor parameter ElementHandlerAttribute(Type handlerType) with [DynamicallyAccessedMembers] annotation). Only minimal IL2026 suppressions remain where needed.

@simonrozsival simonrozsival changed the title [net10.0] Use ElementHandlerAttribute instead of DI for built-in visual elements [net11.0] Use ElementHandlerAttribute instead of DI for built-in visual elements Nov 26, 2025
@simonrozsival
Copy link
Member

/azp run

@azure-pipelines
Copy link

Azure Pipelines could not run because the pipeline triggers exclude this branch/path.

@simonrozsival
Copy link
Member

/azp run MAUI-public,MAUI-DeviceTests-public

@azure-pipelines
Copy link

Azure Pipelines could not run because the pipeline triggers exclude this branch/path.

@simonrozsival simonrozsival marked this pull request as ready for review November 26, 2025 13:55
@simonrozsival simonrozsival merged commit b1992d7 into dev/simonrozsival/net10.0-use-element-handler-attributes Nov 26, 2025
4 checks passed
@simonrozsival simonrozsival deleted the copilot/sub-pr-29952-again branch November 26, 2025 13:56
@github-actions github-actions bot locked and limited conversation to collaborators Dec 27, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants