WinUI3 Xaml Islands in a class library loaded by Winforms
See the question and my original answer on StackOverflowFor a XAML application, there can be multiple IXamlMetadataProvider instances. By default all this is generated by the tooling and the application defers all XAML metadata resolving to the providers.
When you write your own custom application, the system will still ask at runtime for various information. In your project, since it's a Winforms application, the XAML metadata corresponding the the WinUI3 project is not exposed automatically by the tooling so the app crashes when trying to get it (error handling in UWP/WinUI3/XAML is currently very poor and that's a pitty...).
This XAML metadata provider resides in a file XamlTypeInfo.g.cs
that you can have a look at and is located usually in the temp/generated obj\Debug\net7.0-windows10.0.19041.0
(version can vary) folder.
This is what this XamlTypeInfo.g.cs
file looks like:
namespace MyWinUILibrary.MyWinUILibrary_XamlTypeInfo
{
/// <summary>
/// Main class for providing metadata for the app or library
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.UI.Xaml.Markup.Compiler"," 3.0.0.2312")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public sealed class XamlMetaDataProvider : global::Microsoft.UI.Xaml.Markup.IXamlMetadataProvider
{
...
}
The trick is you cannot reference it the MyWinUILibrary.MyWinUILibrary_XamlTypeInfo.XamlMetaDataProvider
class directly, as there's a chicken vs egg problem (the project will not compile before the file is generated and it will only be generated when the project compiles...).
So what you can do is load it by reflection at startup. Here is a modified version of your app that works better:
public class DummyApp : Application, IXamlMetadataProvider
{
private readonly XamlControlsXamlMetaDataProvider provider = new();
private readonly IXamlMetadataProvider _myLibProvider;
public DummyApp()
{
// find the generated IXamlMetadataProvider for this lib
var type = GetType().Assembly.GetTypes()
.FirstOrDefault(t =>
typeof(IXamlMetadataProvider).IsAssignableFrom(t) &&
t.GetCustomAttribute<GeneratedCodeAttribute>() != null);
_myLibProvider = (IXamlMetadataProvider)Activator.CreateInstance(type);
}
public IXamlType GetXamlType(Type type)
{
var ret = provider.GetXamlType(type);
ret ??= _myLibProvider.GetXamlType(type);
return ret;
}
public IXamlType GetXamlType(string fullName)
{
var ret = provider.GetXamlType(fullName);
ret ??= _myLibProvider.GetXamlType(fullName);
return ret;
}
public XmlnsDefinition[] GetXmlnsDefinitions()
{
var ret = provider.GetXmlnsDefinitions();
ret ??= _myLibProvider.GetXmlnsDefinitions();
return ret;
}
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
Resources.MergedDictionaries.Add(new XamlControlsResources());
base.OnLaunched(args);
}
}