Browse Source

Add compatibility hack for older compiled bindings.

Previously, `CompiledBindingPathBuilder` didn't have a `TemplatedParent` method and instead the XAML compiler rewrite templated parent bindings to be a `$self.TemplateParent` property binding. resulting in extraneous logs.

Add a constructor with an  `apiVersion`  to `CompiledBindingPathBuilder` which will be used by newer versions of the XAML compiler, and if a usage is detected using an `apiVersion` of 0, then upgrade `$self.TemplatedParent` to use a `TemplatedParentPathElement`.
refactor/bindingexpressions-in-valuestore
Steven Kirk 3 years ago
parent
commit
523a2bc369
  1. 8
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlBindingPathHelper.cs
  2. 25
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs

8
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlBindingPathHelper.cs

@ -900,8 +900,14 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public XamlILNodeEmitResult Emit(XamlIlEmitContext context, IXamlILEmitter codeGen)
{
var intType = context.Configuration.TypeSystem.GetType("System.Int32");
var types = context.GetAvaloniaTypes();
codeGen.Newobj(types.CompiledBindingPathBuilder.FindConstructor());
// We're calling the CompiledBindingPathBuilder(int apiVersion) with an apiVersion
// of 1 to indicate that we don't want TemplatedParent compatibility hacks enabled.
codeGen
.Ldc_I4(1)
.Newobj(types.CompiledBindingPathBuilder.FindConstructor(new() { intType }));
foreach (var transform in _transformElements)
{

25
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs

@ -107,9 +107,18 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
public class CompiledBindingPathBuilder
{
private readonly int _apiVersion;
private object? _rawSource;
private readonly List<ICompiledBindingPathElement> _elements = new();
public CompiledBindingPathBuilder()
{
}
// TODO12: Remove this constructor. apiVersion is only needed for compatibility with
// versions of Avalonia which used $self.Property() for building TemplatedParent bindings.
public CompiledBindingPathBuilder(int apiVersion) => _apiVersion = apiVersion;
public CompiledBindingPathBuilder Not()
{
_elements.Add(new NotExpressionPathElement());
@ -118,7 +127,21 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
public CompiledBindingPathBuilder Property(IPropertyInfo info, Func<WeakReference<object?>, IPropertyInfo, IPropertyAccessor> accessorFactory)
{
_elements.Add(new PropertyElement(info, accessorFactory, _elements.Count == 0));
// Older versions of Avalonia used $self.Property() for building TemplatedParent bindings.
// Try to detect this and upgrade to using a TemplatedParentPathElement so that logging works
// correctly.
if (_apiVersion == 0 &&
info.Name == "TemplatedParent" &&
_elements.Count >= 1 &&
_elements[_elements.Count - 1] is SelfPathElement)
{
_elements.Add(new TemplatedParentPathElement());
}
else
{
_elements.Add(new PropertyElement(info, accessorFactory, _elements.Count == 0));
}
return this;
}

Loading…
Cancel
Save