diff --git a/src/ComputeSharp.UI/ComputeSharp.UI.projitems b/src/ComputeSharp.UI/ComputeSharp.UI.projitems
index 56d28d6b2..5d500adc7 100644
--- a/src/ComputeSharp.UI/ComputeSharp.UI.projitems
+++ b/src/ComputeSharp.UI/ComputeSharp.UI.projitems
@@ -17,6 +17,7 @@
+
diff --git a/src/ComputeSharp.UI/Helpers/SwapChainManager.cs b/src/ComputeSharp.UI/Helpers/SwapChainManager.cs
index e5322bf4d..c999eebd1 100644
--- a/src/ComputeSharp.UI/Helpers/SwapChainManager.cs
+++ b/src/ComputeSharp.UI/Helpers/SwapChainManager.cs
@@ -20,7 +20,6 @@
using Windows.System;
using Windows.UI.Xaml.Controls;
#endif
-using WinRT;
#if WINDOWS_UWP
namespace ComputeSharp.Uwp.Helpers;
@@ -233,9 +232,7 @@ public SwapChainManager(TOwner owner, GraphicsDevice device)
// IDXGISwapChain reference just created and set that as the swap chain panel to use.
fixed (ISwapChainPanelNative** swapChainPanelNative = this.swapChainPanelNative)
{
- Guid guid = new(0x63AAD0B8, 0x7C24, 0x40FF, 0x85, 0xA8, 0x64, 0x0D, 0x94, 0x4C, 0xC3, 0x25);
-
- ((IWinRTObject)owner).NativeObject.TryAs(guid, out *(nint*)swapChainPanelNative).Assert();
+ SwapChainPanelNativeMarshaller.GetNativeObject(owner, swapChainPanelNative);
}
// Get the underlying ID3D12Device in use
diff --git a/src/ComputeSharp.UI/Helpers/SwapChainPanelNativeMarshaller.cs b/src/ComputeSharp.UI/Helpers/SwapChainPanelNativeMarshaller.cs
new file mode 100644
index 000000000..12315dc89
--- /dev/null
+++ b/src/ComputeSharp.UI/Helpers/SwapChainPanelNativeMarshaller.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Runtime.CompilerServices;
+using ComputeSharp.Core.Extensions;
+using ComputeSharp.Win32;
+#if !WINDOWS_UWP
+using Microsoft.UI.Xaml.Controls;
+#endif
+using System.Runtime.InteropServices;
+#if WINDOWS_UWP
+using Windows.UI.Xaml.Controls;
+#endif
+using WinRT;
+
+#if WINDOWS_UWP
+namespace ComputeSharp.Uwp.Helpers;
+#else
+namespace ComputeSharp.WinUI.Helpers;
+#endif
+
+///
+/// A helper type to handle marshalling objects for native interop.
+///
+internal static unsafe class SwapChainPanelNativeMarshaller
+{
+ ///
+ /// Retrieves the underlying object for an input instance.
+ ///
+ /// The input instance to unwrap.
+ /// A pointer to the resulting object to retrieve.
+ public static void GetNativeObject(SwapChainPanel managedObject, ISwapChainPanelNative** nativeObject)
+ {
+#if WINDOWS_UWP
+ ReadOnlySpan data =
+ [
+ 0xD2, 0x19, 0x2F, 0xF9,
+ 0xDE, 0x3A,
+ 0xA6, 0x45,
+ 0xA2,
+ 0x0C,
+ 0xF6,
+ 0xF1,
+ 0xEA,
+ 0x90,
+ 0x55,
+ 0x4B
+ ];
+#else
+ ReadOnlySpan data =
+ [
+ 0xB8, 0xD0, 0xAA, 0x63,
+ 0x24, 0x7C,
+ 0xFF, 0x40,
+ 0x85,
+ 0xA8,
+ 0x64,
+ 0x0D,
+ 0x94,
+ 0x4C,
+ 0xC3,
+ 0x25
+ ];
+#endif
+ // Unwrap and get the 'ISwapChainPanelNative' interface with the right IID depending on the UI framework
+ ((IWinRTObject)managedObject).NativeObject.TryAs(
+ iid: Unsafe.As(ref MemoryMarshal.GetReference(data)),
+ ppv: out *(nint*)nativeObject).Assert();
+ }
+}
\ No newline at end of file