microsoft / microsoft-ui-xaml

WinUI: a modern UI framework with a rich set of controls and styles to build dynamic and high-performing Windows applications.
MIT License
6.38k stars 683 forks source link

TargetInvocationException when using a DependencyProperty bound to ObservableCollection<Guid?> #10097

Open mavaa opened 1 month ago

mavaa commented 1 month ago

Describe the bug

The attached project illustrates our problem. We have an ObservableCollection<Guid?> that we bind to a DependencyProperty and use to display a list and a counter of unique IDs. Up until Visual Studio v 17.11.4 this was working fine, but after upgrading to 17.11.5 (and the WindowsAppSDK from 1.5.240428000 to 1.6.240923002) the following exception pasted below started happening during startup and the initial setting of the property. We worked around this temporarily by staying at VS 17.11.4 and the older WindowsAppSDK, but this week it seems like devops pipelines has upgraded to the new version, causing all our builds to crash with the same error during startup. This also confirms that the issue happens if you run VS 17.11.5 (assuming that's what the devops runner is using), and WindowsAppSDK 1.5.240428000.

System.Reflection.TargetInvocationException
  HResult=0x80131604
  Message=Exception has been thrown by the target of an invocation.
  Source=System.Private.CoreLib
  StackTrace:
   at System.RuntimeFieldHandle.GetValue(RtFieldInfo field, Object instance, RuntimeType fieldType, RuntimeType declaringType, Boolean& domainInitialized)
   at System.Reflection.RtFieldInfo.GetValue(Object obj)
   at WinRT.GuidGenerator.GetIID(Type type)
   at WinRT.ComWrappersSupport.<GetInterfaceTableEntries>g__AddInterfaceToVtable|16_1(Type iface, List`1 entries, Boolean hasCustomIMarshalInterface)
   at WinRT.ComWrappersSupport.<GetInterfaceTableEntries>g__GetInterfaceTableEntriesForJitEnvironment|16_2(Type type, List`1 entries, Boolean hasCustomIMarshalInterface)
   at WinRT.ComWrappersSupport.GetInterfaceTableEntries(Type type)
   at WinRT.DefaultComWrappers.<>c.<ComputeVtables>b__7_0(Type type)
   at System.Runtime.CompilerServices.ConditionalWeakTable`2.GetValueLocked(TKey key, CreateValueCallback createValueCallback)
   at System.Runtime.CompilerServices.ConditionalWeakTable`2.GetValue(TKey key, CreateValueCallback createValueCallback)
   at WinRT.DefaultComWrappers.ComputeVtables(Object obj, CreateComInterfaceFlags flags, Int32& count)
   at System.Runtime.InteropServices.ComWrappers.TryGetOrCreateComInterfaceForObjectInternal(ObjectHandleOnStack comWrappersImpl, Int64 wrapperId, ObjectHandleOnStack instance, CreateComInterfaceFlags flags, IntPtr& retValue)
   at System.Runtime.InteropServices.ComWrappers.TryGetOrCreateComInterfaceForObjectInternal(ComWrappers impl, Object instance, CreateComInterfaceFlags flags, IntPtr& retValue)
   at System.Runtime.InteropServices.ComWrappers.GetOrCreateComInterfaceForObject(Object instance, CreateComInterfaceFlags flags)
   at WinRT.ComWrappersSupport.CreateCCWForObjectForABI(Object obj, Guid iid)
   at WinRT.ComWrappersSupport.CreateCCWForObjectForMarshaling(Object obj, Guid iid)
   at WinRT.MarshalInspectable`1.CreateMarshaler2(T o, Guid iid, Boolean unwrapObject)
   at WinRT.MarshalInspectable`1.CreateMarshaler2(T o, Boolean unwrapObject)
   at ABI.Microsoft.UI.Xaml.IDependencyObjectMethods.SetValue(IObjectReference _obj, DependencyProperty dp, Object value)
   at Microsoft.UI.Xaml.DependencyObject.SetValue(DependencyProperty dp, Object value)
   at TestNullableGuidObservableCollection.SelectionCounter.set_SelectedItems(ObservableCollection`1 value) in C:\Users\martin\source\repos\TestNullableGuidObservableCollection\TestNullableGuidObservableCollection\SelectionCounter.xaml.cs:line 43
   at TestNullableGuidObservableCollection.MainWindow.XamlBindingSetters.Set_TestNullableGuidObservableCollection_SelectionCounter_SelectedItems(SelectionCounter obj, ObservableCollection`1 value, String targetNullValue) in C:\Users\martin\source\repos\TestNullableGuidObservableCollection\TestNullableGuidObservableCollection\obj\x64\Debug\net8.0-windows10.0.19041.0\MainWindow.g.cs:line 27
   at TestNullableGuidObservableCollection.MainWindow.MainWindow_obj1_Bindings.Update_SelectedItems(ObservableCollection`1 obj, Int32 phase) in C:\Users\martin\source\repos\TestNullableGuidObservableCollection\TestNullableGuidObservableCollection\obj\x64\Debug\net8.0-windows10.0.19041.0\MainWindow.g.cs:line 178
   at TestNullableGuidObservableCollection.MainWindow.MainWindow_obj1_Bindings.Update_(MainWindow obj, Int32 phase) in C:\Users\martin\source\repos\TestNullableGuidObservableCollection\TestNullableGuidObservableCollection\obj\x64\Debug\net8.0-windows10.0.19041.0\MainWindow.g.cs:line 165
   at TestNullableGuidObservableCollection.MainWindow.MainWindow_obj1_Bindings.Update() in C:\Users\martin\source\repos\TestNullableGuidObservableCollection\TestNullableGuidObservableCollection\obj\x64\Debug\net8.0-windows10.0.19041.0\MainWindow.g.cs:line 122
   at TestNullableGuidObservableCollection.MainWindow.MainWindow_obj1_Bindings.Initialize() in C:\Users\martin\source\repos\TestNullableGuidObservableCollection\TestNullableGuidObservableCollection\obj\x64\Debug\net8.0-windows10.0.19041.0\MainWindow.g.cs:line 116
   at TestNullableGuidObservableCollection.MainWindow.MainWindow_obj1_Bindings.Activated(Object obj, WindowActivatedEventArgs data) in C:\Users\martin\source\repos\TestNullableGuidObservableCollection\TestNullableGuidObservableCollection\obj\x64\Debug\net8.0-windows10.0.19041.0\MainWindow.g.cs:line 150
   at WinRT._EventSource_global__Windows_Foundation_TypedEventHandler_object__global__Microsoft_UI_Xaml_WindowActivatedEventArgs_.EventState.<GetEventInvoke>b__1_0(Object sender, WindowActivatedEventArgs args)
   at WinRT.GenericTypeInstantiations.Windows_Foundation_TypedEventHandler_2_object__Microsoft_UI_Xaml_WindowActivatedEventArgs.Do_Abi_Invoke(IntPtr thisPtr, IntPtr sender, IntPtr args)

  This exception was originally thrown at this call stack:
    [External Code]

Inner Exception 1:
TypeInitializationException: The type initializer for 'ABI.System.Collections.Generic.IList`1' threw an exception.

Inner Exception 2:
TypeInitializationException: The type initializer for 'ABI.System.Collections.Generic.IListMethods`1' threw an exception.

Inner Exception 3:
ArgumentException: GenericArguments[1], 'ABI.System.Nullable`1[System.Guid]', on 'ABI.System.Collections.Generic.IListMethods`2[T,TAbi]' violates the constraint of type 'TAbi'.

Inner Exception 4:
TypeLoadException: GenericArguments[1], 'ABI.System.Nullable`1[System.Guid]', on 'ABI.System.Collections.Generic.IListMethods`2[T,TAbi]' violates the constraint of type parameter 'TAbi'.

TestNullableGuidObservableCollection.zip

Steps to reproduce the bug

  1. Open the attached example solution
  2. Build and run
  3. The exception above happens during startup

Expected behavior

For the attached application to start up fine, and no error to occur.

Screenshots

No response

NuGet package version

WinUI 3 - Windows App SDK 1.6.1: 1.6.240923002

Windows version

Windows 11 (21H2): Build 22000

Additional context

No response

mavaa commented 1 month ago

We have also verified that the issue happens on Windows 11 (23H2) Build 22631.4317

manodasanW commented 1 month ago

This has already been fixed in the latest Windows SDK projection update which will be available by default in next month's .NET SDK servicing update. In the meantime, you can use the WindowsSdkPackageVersion property to pick up a newer version of the package than the default. In your case, since you target 19041 and .NET 8, you can use the put the below in your csproj or a common props file. Once next month's .NET SDK servicing update is out, you can remove it.

  <WindowsSdkPackageVersion>10.0.19041.53</WindowsSdkPackageVersion>