Browse Source

Remove IAvaloniaPropertyVisitor.

It was only used internally in creating `ISetterInstance`s so add a virtual method to `AvaloniaProperty` to do this explicitly without generic virtual methods.
pull/8022/head
Steven Kirk 4 years ago
parent
commit
6df672e4c0
  1. 11
      src/Avalonia.Base/AvaloniaProperty.cs
  2. 32
      src/Avalonia.Base/DirectPropertyBase.cs
  3. 32
      src/Avalonia.Base/StyledPropertyBase.cs
  4. 65
      src/Avalonia.Base/Styling/Setter.cs
  5. 32
      src/Avalonia.Base/Utilities/IAvaloniaPropertyVisitor.cs
  6. 11
      tests/Avalonia.Base.UnitTests/AvaloniaPropertyTests.cs

11
src/Avalonia.Base/AvaloniaProperty.cs

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using Avalonia.Data;
using Avalonia.Data.Core;
using Avalonia.Styling;
using Avalonia.Utilities;
namespace Avalonia
@ -454,15 +455,6 @@ 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="visitor">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> visitor, ref TData data)
where TData : struct;
/// <summary>
/// Routes an untyped ClearValue call to a typed call.
/// </summary>
@ -508,6 +500,7 @@ namespace Avalonia
BindingPriority priority);
internal abstract void RouteInheritanceParentChanged(AvaloniaObject o, AvaloniaObject? oldParent);
internal abstract ISetterInstance CreateSetterInstance(IStyleable target, object? value);
/// <summary>
/// Overrides the metadata for the property on the specified type.

32
src/Avalonia.Base/DirectPropertyBase.cs

@ -1,6 +1,7 @@
using System;
using Avalonia.Data;
using Avalonia.Reactive;
using Avalonia.Styling;
using Avalonia.Utilities;
namespace Avalonia
@ -120,12 +121,6 @@ namespace Avalonia
base.OverrideMetadata(type, metadata);
}
/// <inheritdoc/>
public override void Accept<TData>(IAvaloniaPropertyVisitor<TData> visitor, ref TData data)
{
visitor.Visit(this, ref data);
}
/// <inheritdoc/>
internal override void RouteClearValue(AvaloniaObject o)
{
@ -181,5 +176,30 @@ namespace Avalonia
{
throw new NotSupportedException("Direct properties do not support inheritance.");
}
internal override ISetterInstance CreateSetterInstance(IStyleable target, object? value)
{
if (value is IBinding binding)
{
return new PropertySetterBindingInstance<TValue>(
target,
this,
binding);
}
else if (value is ITemplate template && !typeof(ITemplate).IsAssignableFrom(PropertyType))
{
return new PropertySetterLazyInstance<TValue>(
target,
this,
() => (TValue)template.Build());
}
else
{
return new PropertySetterInstance<TValue>(
target,
this,
(TValue)value!);
}
}
}
}

32
src/Avalonia.Base/StyledPropertyBase.cs

@ -2,6 +2,7 @@ using System;
using System.Diagnostics;
using Avalonia.Data;
using Avalonia.Reactive;
using Avalonia.Styling;
using Avalonia.Utilities;
namespace Avalonia
@ -158,12 +159,6 @@ namespace Avalonia
base.OverrideMetadata(type, metadata);
}
/// <inheritdoc/>
public override void Accept<TData>(IAvaloniaPropertyVisitor<TData> visitor, ref TData data)
{
visitor.Visit(this, ref data);
}
/// <summary>
/// Gets the string representation of the property.
/// </summary>
@ -237,6 +232,31 @@ namespace Avalonia
o.InheritanceParentChanged(this, oldParent);
}
internal override ISetterInstance CreateSetterInstance(IStyleable target, object? value)
{
if (value is IBinding binding)
{
return new PropertySetterBindingInstance<TValue>(
target,
this,
binding);
}
else if (value is ITemplate template && !typeof(ITemplate).IsAssignableFrom(PropertyType))
{
return new PropertySetterLazyInstance<TValue>(
target,
this,
() => (TValue)template.Build());
}
else
{
return new PropertySetterInstance<TValue>(
target,
this,
(TValue)value!);
}
}
private object? GetDefaultBoxedValue(Type type)
{
_ = type ?? throw new ArgumentNullException(nameof(type));

65
src/Avalonia.Base/Styling/Setter.cs

@ -16,7 +16,7 @@ namespace Avalonia.Styling
/// A <see cref="Setter"/> is used to set a <see cref="AvaloniaProperty"/> value on a
/// <see cref="AvaloniaObject"/> depending on a condition.
/// </remarks>
public class Setter : ISetter, IAnimationSetter, IAvaloniaPropertyVisitor<Setter.SetterVisitorData>
public class Setter : ISetter, IAnimationSetter
{
private object? _value;
@ -68,68 +68,7 @@ namespace Avalonia.Styling
throw new InvalidOperationException("Setter.Property must be set.");
}
var data = new SetterVisitorData
{
target = target,
value = Value,
};
Property.Accept(this, ref data);
return data.result!;
}
void IAvaloniaPropertyVisitor<SetterVisitorData>.Visit<T>(
StyledPropertyBase<T> property,
ref SetterVisitorData data)
{
if (data.value is IBinding binding)
{
data.result = new PropertySetterBindingInstance<T>(
data.target,
property,
binding);
}
else if (data.value is ITemplate template && !typeof(ITemplate).IsAssignableFrom(property.PropertyType))
{
data.result = new PropertySetterLazyInstance<T>(
data.target,
property,
() => (T)template.Build());
}
else
{
data.result = new PropertySetterInstance<T>(
data.target,
property,
(T)data.value!);
}
}
void IAvaloniaPropertyVisitor<SetterVisitorData>.Visit<T>(
DirectPropertyBase<T> property,
ref SetterVisitorData data)
{
if (data.value is IBinding binding)
{
data.result = new PropertySetterBindingInstance<T>(
data.target,
property,
binding);
}
else if (data.value is ITemplate template && !typeof(ITemplate).IsAssignableFrom(property.PropertyType))
{
data.result = new PropertySetterLazyInstance<T>(
data.target,
property,
() => (T)template.Build());
}
else
{
data.result = new PropertySetterInstance<T>(
data.target,
property,
(T)data.value!);
}
return Property.CreateSetterInstance(target, Value);
}
private struct SetterVisitorData

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

@ -1,32 +0,0 @@
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);
}
}

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

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using Avalonia.Data;
using Avalonia.Styling;
using Avalonia.Utilities;
using Xunit;
@ -146,11 +147,6 @@ 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(
AvaloniaObject o,
IObservable<BindingValue<object>> source,
@ -186,6 +182,11 @@ namespace Avalonia.Base.UnitTests
{
throw new NotImplementedException();
}
internal override ISetterInstance CreateSetterInstance(IStyleable target, object value)
{
throw new NotImplementedException();
}
}
private class Class1 : AvaloniaObject

Loading…
Cancel
Save