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

WASM issue with ToString on CustomAttributeData from System.Reflection #10660

Open
michael-hawker opened this issue Dec 5, 2022 · 4 comments
Labels
area/xBind 🪢 Categorizes an issue or PR as relevant to x:Bind difficulty/medium 🤔 Categorizes an issue for which the difficulty level is reachable with a good understanding of WinUI kind/bug Something isn't working project/binding 🪢 Categorizes an issue or PR as relevant to the binding engine

Comments

@michael-hawker
Copy link

Current behavior

Have been attempting to read custom assembly metadata attributes in WASM for Toolkit Labs. I think it may be working in the stand-alone Uno project that I built, but need to investigate further.

However, when I was setting up my sample project I had a lot of trouble with CustomAttributeData for what was a straight-forward scenario with UWP to bind and dump with ToString.

My initial attempt resulted in a compile error:

  1. Attempt 1 - WASM build error:
1> C:\Users\source\repos\UnoTestWASMAssemblyMetadata\UnoTestWASMAssemblyMetadata\UnoTestWASMAssemblyMetadata.Wasm\Uno.UI.SourceGenerators\Uno.UI.SourceGenerators.XamlGenerator.XamlCodeGenerator\MainPage_6d2410ab684b9af9dea603e399cb27c8.cs(200,212,200,213): error CS1001: Identifier expected

Couldn't seem to load intermediary file to see what it was complaining about in more detail.

And then a runtime error trying to do the ToString in code-behind:

  1. Attempt 2 & 3 - InvalidCastException at Runtime (WASM)
Runtime Stack Trace from Edge

VM108:1
fail: Uno.UI.Dispatching.CoreDispatcher[0] Dispatcher unhandled exception System.InvalidOperationException: Failed to load UnoTestWASMAssemblyMetadata.MainPage: System.InvalidCastException: Specified cast is not valid. at System.Reflection.CustomAttributeTypedArgument.ToString(Boolean typed) in D:\a\Uno.DotnetRuntime.WebAssembly\Uno.DotnetRuntime.WebAssembly\runtime\src\libraries\System.Private.CoreLib\src\System\Reflection\CustomAttributeTypedArgument.cs:line 60 at System.Reflection.CustomAttributeTypedArgument.ToString() in D:\a\Uno.DotnetRuntime.WebAssembly\Uno.DotnetRuntime.WebAssembly\runtime\src\libraries\System.Private.CoreLib\src\System\Reflection\CustomAttributeTypedArgument.cs:line 36 at System.Reflection.CustomAttributeData.ToString() in D:\a\Uno.DotnetRuntime.WebAssembly\Uno.DotnetRuntime.WebAssembly\runtime\src\libraries\System.Private.CoreLib\src\System\Reflection\CustomAttributeData.cs:line 66 at UnoTestWASMAssemblyMetadata.MainPage.<>c.<.ctor>b__4_0(CustomAttributeData i) in C:\Users\mhawker\source\repos\UnoTestWASMAssemblyMetadata\UnoTestWASMAssemblyMetadata\UnoTestWASMAssemblyMetadata.Shared\MainPage.xaml.cs:line 30 at System.Linq.Enumerable.SelectIListIterator`2[[System.Reflection.CustomAttributeData, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext() in D:\a\Uno.DotnetRuntime.WebAssembly\Uno.DotnetRuntime.WebAssembly\runtime\src\libraries\System.Linq\src\System\Linq\Select.cs:line 280 at System.Collections.Generic.List`1[[System.String, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]..ctor(IEnumerable`1 collection) in D:\a\Uno.DotnetRuntime.WebAssembly\Uno.DotnetRuntime.WebAssembly\runtime\src\libraries\System.Private.CoreLib\src\System\Collections\Generic\List.cs:line 85 at System.Linq.Enumerable.ToList[String](IEnumerable`1 source) in D:\a\Uno.DotnetRuntime.WebAssembly\Uno.DotnetRuntime.WebAssembly\runtime\src\libraries\System.Linq\src\System\Linq\ToCollection.cs:line 29 at UnoTestWASMAssemblyMetadata.MainPage..ctor() in C:\Users\mhawker\source\repos\UnoTestWASMAssemblyMetadata\UnoTestWASMAssemblyMetadata\UnoTestWASMAssemblyMetadata.Shared\MainPage.xaml.cs:line 30 at UnoTestWASMAssemblyMetadata.Wasm.MetadataBuilder_644.CreateInstance() in C:\Users\mhawker\source\repos\UnoTestWASMAssemblyMetadata\UnoTestWASMAssemblyMetadata\UnoTestWASMAssemblyMetadata.Wasm\Uno.UI.SourceGenerators\Uno.UI.SourceGenerators.BindableTypeProviders.BindableTypeProvidersSourceGenerator\BindableMetadata.g.cs:line 23434 at Windows.UI.Xaml.Controls.Frame.CreatePageInstance(Type sourcePageType) in /home/vsts/work/1/s/src/Uno.UI/UI/Xaml/Controls/Frame/Frame.cs:line 454 at Windows.UI.Xaml.PagePool.DequeuePage(Type pageType) in /home/vsts/work/1/s/src/Uno.UI/UI/Xaml/PagePool.cs:line 69 at Windows.UI.Xaml.Controls.Frame.CreatePageInstanceCached(Type sourcePageType) in /home/vsts/work/1/s/src/Uno.UI/UI/Xaml/Controls/Frame/Frame.cs:line 444 at Windows.UI.Xaml.Controls.Frame.EnsurePageInitialized(PageStackEntry entry) in /home/vsts/work/1/s/src/Uno.UI/UI/Xaml/Controls/Frame/Frame.cs:line 435 at Windows.UI.Xaml.Controls.Frame.InnerNavigate(PageStackEntry entry, NavigationMode mode) in /home/vsts/work/1/s/src/Uno.UI/UI/Xaml/Controls/Frame/Frame.cs:line 283 at UnoTestWASMAssemblyMetadata.App.OnNavigationFailed(Object sender, NavigationFailedEventArgs e) in C:\Users\mhawker\source\repos\UnoTestWASMAssemblyMetadata\UnoTestWASMAssemblyMetadata\UnoTestWASMAssemblyMetadata.Shared\App.xaml.cs:line 107 at Windows.UI.Xaml.Controls.Frame.InnerNavigate(PageStackEntry entry, NavigationMode mode) in /home/vsts/work/1/s/src/Uno.UI/UI/Xaml/Controls/Frame/Frame.cs:line 300 at Windows.UI.Xaml.Controls.Frame.Navigate(Type sourcePageType, Object parameter, NavigationTransitionInfo infoOverride) in /home/vsts/work/1/s/src/Uno.UI/UI/Xaml/Controls/Frame/Frame.cs:line 276 at Windows.UI.Xaml.Controls.Frame.Navigate(Type sourcePageType, Object parameter) in /home/vsts/work/1/s/src/Uno.UI/UI/Xaml/Controls/Frame/Frame.cs:line 271 at UnoTestWASMAssemblyMetadata.App.OnLaunched(LaunchActivatedEventArgs args) in C:\Users\mhawker\source\repos\UnoTestWASMAssemblyMetadata\UnoTestWASMAssemblyMetadata\UnoTestWASMAssemblyMetadata.Shared\App.xaml.cs:line 93 at Windows.UI.Xaml.Application.Initialize() in /home/vsts/work/1/s/src/Uno.UI/UI/Xaml/Application.wasm.cs:line 130 at Uno.UI.Dispatching.CoreDispatcher.InvokeOperationSafe(UIAsyncOperation operation) in /home/vsts/work/1/s/src/Uno.UI.Dispatching/Core/CoreDispatcher.cs:line 337
  eval @ VM108:1


Think pointing to here: https://github.com/dotnet/runtimelab/blob/04b092003db5ba207d4fa3f3becb7f01828bf16c/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeTypedArgument.cs#L60

Expected behavior

Running on UWP:

image

How to reproduce it (as minimally and precisely as possible)

  1. Create a new Xamarin | UWP Uno Project App in VS 2022
  2. Modify MainPage.xaml.cs:
        // Attempt 1
        public IList<CustomAttributeData> AssemblyMetadata { get; set; }

        // Attempt 2+
        ////public IList<string> AssemblyMetadata { get; set; }

        public MainPage()
        {
            // Note all commented out code worked fine on UWP.

            // Attempt 1: Initially tried this directly:
            AssemblyMetadata = Assembly.GetExecutingAssembly().GetCustomAttributesData();

            // Attempt 2: Then this, but it didn't work (InvalidCastException)
            //// AssemblyMetadata = Assembly.GetExecutingAssembly().GetCustomAttributesData().Select(i => i.ToString()).ToList();

            // Attempt 3
            /*List<string> tmp = new();

            foreach (var metadata in Assembly.GetExecutingAssembly().GetCustomAttributesData())
            {
                tmp.Add(metadata.ToString()); // Failing Line in ToString Call
            }

            AssemblyMetadata = tmp;*/

            // Attempt 4 - Avoiding ToString on the type and using other values works fine
            /*AssemblyMetadata = Assembly.GetExecutingAssembly().GetCustomAttributesData().Select(i => i.AttributeType.Name).ToList();*/

            this.InitializeComponent();
        }
  1. Add to MainPage.xaml
<StackPanel Margin="32" Spacing="8">
        <ItemsControl ItemsSource="{x:Bind AssemblyMetadata}">
            <ItemsControl.ItemTemplate>
                <!--  Attempt 1 (worked fine on UWP)  -->
                <DataTemplate x:DataType="ref:CustomAttributeData">
                    <TextBlock Text="{x:Bind (ref:CustomAttributeData).ToString()}" />
                </DataTemplate>
                <!--  Attempt 2+  -->
                <!--<DataTemplate>
                    <TextBlock Text="{Binding}" />
                </DataTemplate>-->
            </ItemsControl.ItemTemplate>
        </ItemsControl>
        <TextBlock>
            <Run Text="Attribute Count:" />
            <Run Text="{x:Bind AssemblyMetadata.Count}" />
        </TextBlock>
    </StackPanel>

Attached project zip of all scenarios:

UnoTestWASMAssemblyMetadata.zip

Workaround

Not sure how to get full information contained within the type as easily as was provided with ToString, mind you this is a more contrived scenario, as in our case we're getting a specific attribute (though in our other project we don't see that listed, thus why I was building this example).

Works on UWP/WinUI

Yes

Environment

Uno.UI / Uno.UI.WebAssembly / Uno.UI.Skia

NuGet package version(s)

Uno.UI.WebAssembly 4.6.19

Affected platforms

WebAssembly

IDE

Visual Studio 2022

IDE version

17.4.0

Relevant plugins

No response

Anything else we need to know?

Not sure if another edge case of #7893? Though the ToString seems to be involved in the later attempts. Maybe it's two slightly different issues underneath?

Will go back to Labs and try and compare to see why I'm not seeing the same number of attributes as I did in the sample here at least, so this has given me some insight at least even if it did uncover other issues that I don't think may directly effect us at the moment.

@michael-hawker michael-hawker added difficulty/tbd Categorizes an issue for which the difficulty level needs to be defined. kind/bug Something isn't working triage/untriaged Indicates an issue requires triaging or verification labels Dec 5, 2022
@jeromelaban
Copy link
Member

This looks like there are two separate issues here.

First, it seems that adding a function invocation to the pathless cast is not working well, but even when doing this:

<TextBlock DataContext="{x:Bind (ref:CustomAttributeData))"
                   Text="{Binding}" />

I'm getting:

System.InvalidCastException: Unable to cast object of type 'Microsoft.CodeAnalysis.CSharp.Syntax.AssignmentExpressionSyntax' to type 'Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax'

I'm not able to repro in Unit Tests, so there must be something else that breaks that particular scenario.

That being said, you're not forced to use x:Bind here, and a simple:

<TextBlock Text="{Binding}" />

Will be enough as a workaround.

@jeromelaban jeromelaban added area/xBind 🪢 Categorizes an issue or PR as relevant to x:Bind project/binding 🪢 Categorizes an issue or PR as relevant to the binding engine and removed triage/untriaged Indicates an issue requires triaging or verification labels Dec 6, 2022
@michael-hawker
Copy link
Author

Thanks @jeromelaban, I didn't try just using {Binding} but with the original object type. That does output the ToString result properly! 🎉 It is weird that calling the ToString method directly in code-behind causes an exception though? I don't know how it'd take a different path.

Still investigating in Labs what might be going on there with our attributes, but our generation of them is a bit different. This info will help that investigation though. Thanks!

@jeromelaban
Copy link
Member

Great! As for the error with CustomAttribute, I suspect this is a runtime issue that may (or may not) be fixed with .NET 7 (bootstrapper 7.0.x). Could be worth a try.

@michael-hawker
Copy link
Author

Ah, figured out my base issue we had in Labs in regard to where I was retrieving the Metadata (which existed and was valid with our new generation system), but not where I was setting the property/evaluating the bindings... I was basically hitting the #2666 #2872 issues again.

So at least I've got everything I need working for Labs at the moment!

@MartinZikmund MartinZikmund changed the title WASM issue with ToString on CustomAttributeData from System.Reflection WASM issue with ToString on CustomAttributeData from System.Reflection Aug 23, 2023
@MartinZikmund MartinZikmund added difficulty/medium 🤔 Categorizes an issue for which the difficulty level is reachable with a good understanding of WinUI and removed difficulty/tbd Categorizes an issue for which the difficulty level needs to be defined. labels Aug 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/xBind 🪢 Categorizes an issue or PR as relevant to x:Bind difficulty/medium 🤔 Categorizes an issue for which the difficulty level is reachable with a good understanding of WinUI kind/bug Something isn't working project/binding 🪢 Categorizes an issue or PR as relevant to the binding engine
Projects
None yet
Development

No branches or pull requests

3 participants