Skip to content

Commit c0c82df

Browse files
MrJulgrokys
authored andcommitted
Convert IAvaloniaXamlIlParentStackProvider to eager one if needed (#16028)
1 parent 2c1a181 commit c0c82df

File tree

4 files changed

+49
-4
lines changed

4 files changed

+49
-4
lines changed

src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguage.cs

+13-4
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public static (XamlLanguageTypeMappings language, XamlLanguageEmitMappings<IXaml
7676
ContextTypeBuilderCallback = definition =>
7777
{
7878
EmitNameScopeField(rv, typeSystem, definition);
79-
EmitEagerParentStackProvider(rv, typeSystem, definition);
79+
EmitEagerParentStackProvider(rv, typeSystem, definition, runtimeHelpers);
8080
}
8181
};
8282
return (rv, emit);
@@ -104,7 +104,8 @@ private static void EmitNameScopeField(
104104
private static void EmitEagerParentStackProvider(
105105
XamlLanguageTypeMappings mappings,
106106
IXamlTypeSystem typeSystem,
107-
IXamlILContextDefinition<IXamlILEmitter> definition)
107+
IXamlILContextDefinition<IXamlILEmitter> definition,
108+
IXamlType runtimeHelpers)
108109
{
109110
var interfaceType = typeSystem.FindType("Avalonia.Markup.Xaml.XamlIl.Runtime.IAvaloniaXamlIlEagerParentStackProvider");
110111

@@ -122,14 +123,22 @@ private static void EmitEagerParentStackProvider(
122123
typeSystem.FindType("System.Object"),
123124
typeSystem.FindType("System.Type")));
124125

126+
var asEagerParentStackProviderMethod = runtimeHelpers.GetMethod(new FindMethodMethodSignature(
127+
"AsEagerParentStackProvider",
128+
interfaceType,
129+
mappings.ParentStackProvider)
130+
{
131+
IsStatic = true
132+
});
133+
125134
// IAvaloniaXamlIlEagerParentStackProvider? ParentProvider
126-
// => (IAvaloniaXamlIlEagerParentStackProvider)_serviceProvider.GetService(typeof(IAvaloniaXamlIlParentStackProvider))
135+
// => XamlIlRuntimeHelpers.AsEagerParentStackProvider(_serviceProvider.GetService(typeof(IAvaloniaXamlIlParentStackProvider)));
127136
var parentProviderGetter = ImplementInterfacePropertyGetter("ParentProvider");
128137
parentProviderGetter.Generator
129138
.LdThisFld(definition.ParentServiceProviderField)
130139
.Ldtype(mappings.ParentStackProvider)
131140
.EmitCall(serviceProviderGetServiceMethod)
132-
.Castclass(interfaceType)
141+
.EmitCall(asEagerParentStackProviderMethod)
133142
.Ret();
134143

135144
IXamlMethodBuilder<IXamlILEmitter> ImplementInterfacePropertyGetter(string propertyName)

src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
<Compile Include="XamlIl\Runtime\IAvaloniaXamlIlControlTemplateProvider.cs" />
5353
<Compile Include="XamlIl\Runtime\IAvaloniaXamlIlParentStackProvider.cs" />
5454
<Compile Include="XamlIl\Runtime\IAvaloniaXamlIlXmlNamespaceInfoProviderV1.cs" />
55+
<Compile Include="XamlIl\Runtime\XamlIlParentStackProviderWrapper.cs" />
5556
<Compile Include="XamlIl\Runtime\XamlIlRuntimeHelpers.cs" />
5657
<Compile Include="XamlLoadException.cs" />
5758
<Compile Include="XamlTypes.cs" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
4+
namespace Avalonia.Markup.Xaml.XamlIl.Runtime;
5+
6+
/// <summary>
7+
/// Wraps a <see cref="IAvaloniaXamlIlParentStackProvider"/> into a <see cref="IAvaloniaXamlIlEagerParentStackProvider"/>,
8+
/// for backwards compatibility.
9+
/// </summary>
10+
internal sealed class XamlIlParentStackProviderWrapper : IAvaloniaXamlIlEagerParentStackProvider
11+
{
12+
private readonly IAvaloniaXamlIlParentStackProvider _provider;
13+
14+
private IReadOnlyList<object>? _directParentsStack;
15+
16+
public XamlIlParentStackProviderWrapper(IAvaloniaXamlIlParentStackProvider provider)
17+
=> _provider = provider;
18+
19+
public IEnumerable<object> Parents
20+
=> _provider.Parents;
21+
22+
public IReadOnlyList<object> DirectParentsStack
23+
=> _directParentsStack ??= _provider.Parents.Reverse().ToArray();
24+
25+
public IAvaloniaXamlIlEagerParentStackProvider? ParentProvider
26+
=> null;
27+
}

src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs

+8
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,14 @@ private static IResourceNode[] AsResourceNodesStack(IAvaloniaXamlIlParentStackPr
9595
return resourceNodes;
9696
}
9797

98+
/// <summary>
99+
/// Converts a <see cref="IAvaloniaXamlIlParentStackProvider"/> into a
100+
/// <see cref="IAvaloniaXamlIlEagerParentStackProvider"/>.
101+
/// </summary>
102+
public static IAvaloniaXamlIlEagerParentStackProvider AsEagerParentStackProvider(
103+
this IAvaloniaXamlIlParentStackProvider provider)
104+
=> provider as IAvaloniaXamlIlEagerParentStackProvider ?? new XamlIlParentStackProviderWrapper(provider);
105+
98106
// Parent resource nodes are often the same (e.g. most values in a ResourceDictionary), cache the last ones.
99107
private sealed class LastParentStack
100108
{

0 commit comments

Comments
 (0)