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

[Request] Allow self-registration of handlers, etc. #7258

Open
jsuarezruiz opened this issue May 17, 2022 · 6 comments
Open

[Request] Allow self-registration of handlers, etc. #7258

jsuarezruiz opened this issue May 17, 2022 · 6 comments
Labels
area-controls-general General issues that span multiple controls, or common base classes such as View or Element partner Issue or Request from a partner team proposal/open t/enhancement ☀️ New feature or request
Milestone

Comments

@jsuarezruiz
Copy link
Contributor

Description

Imagine a library with a big amount of handlers, effects, etc.

  • If a client-dev wants to use the components - he needs to put a lot of code in the CreateMauiApp() method. If the client-dev uses a NuGet - it will not be obvious that there is an additional step he needs to do to get the components working.
  • We can implement a single UseLibrary() extension method, but there are huge consequences for using such an approach. The problem is as follows - in the UseLibrary() method, we need to register everything - all handlers, renderers, effects, everything. Now the linker will not be able to strip away unused code - even if the client-dev uses only a couple of our controls.
  • It will be very useful if we can introduce a property in the MauiApp class that will allow to dynamically register a handler. For example, the static constructor of a Component1 can execute a call like MauiApp.Current.TryAddHandler(Component1, Component1Handler). This way if a client-dev uses Component1 - the handler will be registered automatically. If the client-dev does not use it - the linker would be able to properly strip away the component and the handler. Note that the name of the method is TryAddHandler() - so it can check if a handler was already registered for this type and not overwrite it.

Public API Changes

We have to analyze possibilities to allow this.

Intended Use-Case

MauiApp.Current.TryAddHandler(Component1, Component1Handler)

@mattleibow
Copy link
Member

One potential use case is to make something like we have in the sample app that allows for a single .UseBigThing() that does not do any registration but grabs hold of the handlers collection and allows for adding later:

https://github.com/dotnet/maui/blob/a51243a75bebc5571e6351e0e93cf6b40a592877/src/Controls/samples/Controls.Sample/Controls/BordelessEntry/BordelessEntryServiceBuilder.cs

// in the builder
builder.UseBorderlessEntry(); // <- bad name, should be UseBigLibrary() or something

// in the xaml control static ctor
BordelessEntryServiceBuilder.TryAddHandler<BordelessEntry, BordelessEntryHandler>();

Both have bad names, but I could see something like SkiaSharp doing this with a:

builder.UseSkiaSharp()

And then in the SKCanvasView (or the SKGLView) static constructors I would register the handlers:

HandlersHelper.TryAddHandler<SKCanvasView, SKCanvasViewHandler>();

This could actually be made to work generally and then Maui exposes this "helper" class like this:

MauiHandlerRegistrar.TryAddHandler<SKCanvasView, SKCanvasViewHandler>();

One issue with this is that this registrar is now a static thing, so should probably live in the Controls layer and Comet can copy. This way we preserve the fact that Core is testable because there is no singleton that lives forever.

@mattleibow mattleibow added the partner Issue or Request from a partner team label May 17, 2022
@mattleibow mattleibow added this to the .NET 7 milestone May 17, 2022
@Eilon Eilon added the legacy-area-controls Label, Button, CheckBox, Slider, Stepper, Switch, Picker, Entry, Editor label May 17, 2022
@PureWeen
Copy link
Member

PureWeen commented May 18, 2022

What if we enable the ability to return the desired handler from the concrete type? I know @Clancey enabled this at one point and then it got lost in the repository shuffle.

If the concrete type could just return the handler type it wants to use. We wouldn't need to pass the handler collection around.

We could have something like

if (concreteType is IHaveMyOwnHandler myOwnHandler)
    return myOwnHandler.GetHandlerType();

And then people could also more easily customize handlers per controls if they wanted to.

@dotMorten
Copy link
Contributor

I support this 1000%. I’m already time after time again seeing people not understanding why our controls don’t work, simply because they didn’t know they needed to call some obscure UseXxx() method in the builder. While I get the technical reason for it, it is incredibly developer unfriendly for 3rd party component customers.

@awalker-dsg
Copy link

awalker-dsg commented Jul 28, 2022

I also support this request. MAUI's lack of self-registration for custom handlers is a major step backward for anyone coming to MAUI from Xamarin and wanting to convert Xamarin custom renderers to handlers.

In Xamarin, we could self-register a custom renderer using the ExportRenderer attribute as in this example for an Entry custom renderer:

    [assembly: ExportRenderer(typeof(Entry), typeof(MyNamespace.Droid.Renderers.EntryRenderer))]

    namespace MyNamespace.Droid.Renderers
    {
        public class EntryRenderer : Xamarin.Forms.Platform.Android.EntryRenderer
        {
            // Custom renderer implementation
        }
    }

We use this pattern for custom renderers in internal NuGet libs that are used by multiple mobile apps within our company. Apps can use the cross-platform base class without having to know anything about the underlying custom renderer.

Now, if I understand the MAUI documentation here and here correctly, every custom renderer or custom handler in our libs will have to be explicitly registered in each app's MauiProgram.CreateMauiApp function. Ugh. This is progress?

@dotMorten
Copy link
Contributor

This is progress?

It is wrt startup time. The attribute approach is pretty bad because it relies on reflection, and it also runs the risk of the optimizer optimizing things away.
Hopefully there's a way we can achieve both. I'm thinking some sort of method or interface a control can implement to hand out the default handler that'll be called if one hasn't been registered. Then there's "just" the matter of ensuring the assembly and class isn't optimized away if it's only referenced in XAML (directly or indirectly).

@ghost
Copy link

ghost commented Jul 11, 2023

We've added this issue to our backlog, and we will work to address it as time and resources allow. If you have any additional information or questions about this issue, please leave a comment. For additional info about issue management, please read our Triage Process.

@Eilon Eilon added area-controls-general General issues that span multiple controls, or common base classes such as View or Element and removed legacy-area-controls Label, Button, CheckBox, Slider, Stepper, Switch, Picker, Entry, Editor labels May 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-controls-general General issues that span multiple controls, or common base classes such as View or Element partner Issue or Request from a partner team proposal/open t/enhancement ☀️ New feature or request
Projects
None yet
Development

No branches or pull requests

8 participants