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

C++/WinRT-based apps consuming C# native modules (which use reflection) cannot use .NetNative, and therefore may be unable to actually ship #6473

Closed
jonthysell opened this issue Nov 9, 2020 · 4 comments
Labels
Area: C#/C++ interop Documentation enhancement External Issue tracked in this repo but change will need to happen in another repo Recommend: Not Planned Recommend that issue should be given Not Planned milestone.
Milestone

Comments

@jonthysell
Copy link
Contributor

jonthysell commented Nov 9, 2020

This repros both in RNW 0.62, 0.63, and seems to be a problem with Visual Studio and/or the C++/WinRT toolchain.

RNW 0.62 uses reflection to implement the "attribute-based" C# implementations for both ReactModule and AttributedViewManager. A C# native module that uses these "attribute-based" implementations (as recommended) will only completely work with a C# based app.

Everything will compile and run fine for Debug. At runtime, the reflection will work to discover the ReactModules and AttributedViewManagers.

When building in Release, with .NetNative enabled, all of the reflection metadata will be stripped from the final binaries, so everything will compile, but at runtime the reflection will fail to discover the modules / view managers. The supported solution is to add a Runtime Directives file to your app, to direct .NetNative to not strip out the metadata.

However, only C# apps support adding this runtime directive file. Just adding the file to a C++/WinRT app will cause a build break when .NetNative tries to run.

One workaround is to not use .NetNative altogether, even on Release builds. While it's supposed to be required to use .NetNative to publish an app on the Store, it's not actually enforced. However, this does mean that your app will not work at all in Windows 10X, which will not run apps that use C# if it hasn't been .NetNative-ized.

In RNW 0.63 this is partially mitigated by the switch from reflection to code-gen. C# native modules written using the attribute-based ReactModule do not rely on runtime reflection, as so work fine with .NetNative. However, AttributedViewManager was not converted to code-gen, so the issue remains.

If it's not confusing enough, imagine you're a community module that needs to support multiple versions of RNW.

If you are writing a C# native module and want to support the full matrix of C++/C# apps and 62/62 with one shared set of code - the only workaround is to avoid using any reflection in your implementation, which means manually implementing the low-level ABI for your module (implementing the IViewManager interfaces directly like C++ developers do for view managers, and calling the various module builder APIs, see Naitve Modules Advanced docs for native modules).

@jonthysell jonthysell added the bug label Nov 9, 2020
@ghost ghost added the Needs: Triage 🔍 New issue that needs to be reviewed by the issue management team (label applied by bot) label Nov 9, 2020
@jonthysell jonthysell changed the title C++/WinRT-based apps consuming C# native modules (which use reflection) cannot use .NetNative, and therefore may be able to actually ship C++/WinRT-based apps consuming C# native modules (which use reflection) cannot use .NetNative, and therefore may be unable to actually ship Nov 9, 2020
@dannyvv
Copy link
Member

dannyvv commented Nov 10, 2020

Note: In 0.63, even when CodeGen is used, For the serialization cases there are still fallback codepaths that rely on reflection. For serialization the codegen is a best effort since due to polymorphism and generics not all possible types used can be guaranteed to be visible during codegen.

@jonthysell
Copy link
Contributor Author

Note: In 0.63, even when CodeGen is used, For the serialization cases there are still fallback codepaths that rely on reflection. For serialization the codegen is a best effort since due to polymorphism and generics not all possible types used can be guaranteed to be visible during codegen.

I didn't realize this and it's good to call out, in case other people start seeing issues.

@jonthysell
Copy link
Contributor Author

This was hit by a customer trying to consume Device Info (c#), Senstive Info (c#), and Static Server (c#) (see #6332) being unable to pacakage for store distribution, and their workaround was to switch their app to C#.

@asklar
Copy link
Member

asklar commented Nov 16, 2020

If we can't find a fix let's document this - also related: #6539

@chrisglein chrisglein added External Issue tracked in this repo but change will need to happen in another repo and removed Needs: Triage 🔍 New issue that needs to be reviewed by the issue management team (label applied by bot) labels Nov 19, 2020
@chrisglein chrisglein added this to the 0.65 milestone Nov 19, 2020
@chrisglein chrisglein modified the milestones: 0.65, Backlog Apr 24, 2021
@jonthysell jonthysell added the Recommend: Not Planned Recommend that issue should be given Not Planned milestone. label Aug 14, 2023
@chrisglein chrisglein closed this as not planned Won't fix, can't repro, duplicate, stale Sep 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: C#/C++ interop Documentation enhancement External Issue tracked in this repo but change will need to happen in another repo Recommend: Not Planned Recommend that issue should be given Not Planned milestone.
Projects
None yet
Development

No branches or pull requests

4 participants