Browse Source

Add an AvaloniaProperty visitor.

We already have some specific internal methods for routing certain methods via an untyped property to a typed property, but adding support for the visitor pattern allows us to support arbitrary use-cases.
pull/3636/head
Steven Kirk 6 years ago
parent
commit
b82ca9aca9
  1. 9
      src/Avalonia.Base/AvaloniaProperty.cs
  2. 7
      src/Avalonia.Base/DirectPropertyBase.cs
  3. 7
      src/Avalonia.Base/StyledPropertyBase.cs
  4. 34
      src/Avalonia.Base/Utilities/IAvaloniaPropertyVisitor.cs
  5. 6
      tests/Avalonia.Base.UnitTests/AvaloniaPropertyTests.cs

9
src/Avalonia.Base/AvaloniaProperty.cs

@ -469,6 +469,15 @@ namespace Avalonia
return Name;
}
/// <summary>
/// Uses the visitor pattern to resolve an untyped property to a typed property.
/// </summary>
/// <typeparam name="TData">The type of user data passed.</typeparam>
/// <param name="vistor">The visitor which will accept the typed property.</param>
/// <param name="data">The user data to pass.</param>
public abstract void Accept<TData>(IAvaloniaPropertyVisitor<TData> vistor, ref TData data)
where TData : struct;
/// <summary>
/// Notifies the <see cref="Changed"/> observable.
/// </summary>

7
src/Avalonia.Base/DirectPropertyBase.cs

@ -1,6 +1,7 @@
using System;
using Avalonia.Data;
using Avalonia.Reactive;
using Avalonia.Utilities;
#nullable enable
@ -101,6 +102,12 @@ namespace Avalonia
return (DirectPropertyMetadata<TValue>)base.GetMetadata(type);
}
/// <inheritdoc/>
public override void Accept<TData>(IAvaloniaPropertyVisitor<TData> vistor, ref TData data)
{
vistor.Visit(this, ref data);
}
/// <inheritdoc/>
internal override void RouteClearValue(IAvaloniaObject o)
{

7
src/Avalonia.Base/StyledPropertyBase.cs

@ -5,6 +5,7 @@ using System;
using System.Diagnostics;
using Avalonia.Data;
using Avalonia.Reactive;
using Avalonia.Utilities;
namespace Avalonia
{
@ -169,6 +170,12 @@ namespace Avalonia
base.OverrideMetadata(type, metadata);
}
/// <inheritdoc/>
public override void Accept<TData>(IAvaloniaPropertyVisitor<TData> vistor, ref TData data)
{
vistor.Visit(this, ref data);
}
/// <summary>
/// Gets the string representation of the property.
/// </summary>

34
src/Avalonia.Base/Utilities/IAvaloniaPropertyVisitor.cs

@ -0,0 +1,34 @@
#nullable enable
namespace Avalonia.Utilities
{
/// <summary>
/// A visitor to resolve an untyped <see cref="AvaloniaProperty"/> to a typed property.
/// </summary>
/// <typeparam name="TData">The type of user data passed.</typeparam>
/// <remarks>
/// Pass an instance that implements this interface to
/// <see cref="AvaloniaProperty.Accept{TData}(IAvaloniaPropertyVisitor{TData}, ref TData)"/>
/// in order to resolve un untyped <see cref="AvaloniaProperty"/> to a typed
/// <see cref="StyledPropertyBase{TValue}"/> or <see cref="DirectPropertyBase{TValue}"/>.
/// </remarks>
public interface IAvaloniaPropertyVisitor<TData>
where TData : struct
{
/// <summary>
/// Called when the property is a styled property.
/// </summary>
/// <typeparam name="T">The property value type.</typeparam>
/// <param name="property">The property.</param>
/// <param name="data">The user data.</param>
void Visit<T>(StyledPropertyBase<T> property, ref TData data);
/// <summary>
/// Called when the property is a direct property.
/// </summary>
/// <typeparam name="T">The property value type.</typeparam>
/// <param name="property">The property.</param>
/// <param name="data">The user data.</param>
void Visit<T>(DirectPropertyBase<T> property, ref TData data);
}
}

6
tests/Avalonia.Base.UnitTests/AvaloniaPropertyTests.cs

@ -3,6 +3,7 @@
using System;
using Avalonia.Data;
using Avalonia.Utilities;
using Xunit;
namespace Avalonia.Base.UnitTests
@ -123,6 +124,11 @@ namespace Avalonia.Base.UnitTests
OverrideMetadata(typeof(T), metadata);
}
public override void Accept<TData>(IAvaloniaPropertyVisitor<TData> vistor, ref TData data)
{
throw new NotImplementedException();
}
internal override IDisposable RouteBind(
IAvaloniaObject o,
IObservable<BindingValue<object>> source,

Loading…
Cancel
Save