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.
Steven Kirk 3 years ago
parent
commit
6df672e4c0

+ 2 - 9
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.

+ 26 - 6
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!);
+            }
+        }
     }
 }

+ 26 - 6
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));

+ 2 - 63
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

+ 0 - 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);
-    }
-}

+ 6 - 5
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