Skip to content

Add reflection-based support for wrapping JS interop calls as C# delegates #61673

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

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

oroztocil
Copy link
Member

@oroztocil oroztocil commented Apr 24, 2025

This is a work-in-progress implementation of AsAsyncFunction extension method for IJSObjectReference. The method creates an asynchronous Func<...> delegate that serves as a C#-native typed wrapper that invokes the referenced JS function via interop.

Sync variant and the full PR description can be added after we finalize implementation design.

This is the reflection-based alternative to #61721.

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-blazor Includes: Blazor, Razor Components label Apr 24, 2025
@oroztocil oroztocil force-pushed the oroztocil/js-interop-function-object-reference branch from 5cdd2a7 to 50fb6ee Compare April 24, 2025 15:47
@oroztocil oroztocil requested a review from javiercn April 24, 2025 16:25
@oroztocil oroztocil changed the title Add support for wrapping JS interop calls as C# delegates Add reflection-based support for wrapping JS interop calls as C# delegates Apr 28, 2025
@oroztocil
Copy link
Member Author

@javiercn Please discuss with @pavelsavara and @maraf what should be done with this feature. We can:

  1. Go ahead with a reflection-based solution (this PR) that introduces one public API method but has bunch of obvious and possibly some non-obvious issues.
  2. Use a simple static solution (Add statically-typed support for wrapping JS interop calls as C# delegates  #61721) which, however, introduces multiple overloads to cover different number of args and void/non-void calls.
  3. Scratch the feature altogether.

Personally, I am for 2 or 3 for the reasons we already went through. However, I want to go ahead with the consensus in the wider team.

@pavelsavara
Copy link
Member

pavelsavara commented Apr 28, 2025

  1. This PR adds reflection and the behavior is leaking into public API. It would be impossible to fix later for trimmability/NAOT.
  2. is much better. I still dislike making OOP over RPC call easy, but that ship sailed for Blazor JS interop.
  3. yes please, who asked for this "feature" anyway.

@javiercn
Copy link
Member

javiercn commented May 6, 2025

This PR adds reflection and the behavior is leaking into public API. It would be impossible to fix later for trimmability/NAOT.

Can you clarify what you mean about this impacting the public API? I'm not sue what you mean about the comment on trimmability/NAOT. What's the specific issue with the pattern (note we do the same thing all over the place).

If the solution to address this were to use a source generator instead, AsAsyncFunction could be replaced with a SG based solution relying on Interceptors, so this shouldn't be a problem.

is much better. I still dislike making OOP over RPC call easy, but that ship sailed for Blazor JS interop.

That's fine, sometimes we can change the approach our customers take, but others we can't.

yes please, who asked for this "feature" anyway.

As for demand, this is covered as part of #31151.

There are common patterns that make this very useful, like being able to import a JSModule and taking a reference to one of its exported functions for use later on, and being able to pass that around as a BCL type as opposed to taking a dependency on JS interop types.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-blazor Includes: Blazor, Razor Components
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants