Răsfoiți Sursa

Correctly implement finding property by name.

Steven Kirk 10 ani în urmă
părinte
comite
20436d95de

+ 21 - 10
src/Perspex.Base/PerspexPropertyRegistry.cs

@@ -157,26 +157,37 @@ namespace Perspex
                 throw new ArgumentException("Invalid property name.");
             }
 
+            string propertyName;
+            var results = GetRegistered(type);
+
             if (parts.Length == 1)
             {
-                var result = GetRegistered(type)
-                    .FirstOrDefault(x => !x.IsAttached && x.Name == parts[0]);
+                propertyName = parts[0];
+            }
+            else
+            {
+                var types = GetImplementedTypes(type);
 
-                if (result != null)
+                if (!types.Contains(parts[0]))
                 {
-                    return result;
+                    results = results.Where(x => x.OwnerType.Name == parts[0]);
                 }
 
-                // A type can .AddOwner an attached property.
-                return GetRegistered(type)
-                    .FirstOrDefault(x => x.Name == parts[0]);
+                propertyName = parts[1];
             }
-            else
+
+            return results.FirstOrDefault(x => x.Name == propertyName);
+        }
+
+        private IEnumerable<string> GetImplementedTypes(Type type)
+        {
+            while (type != null)
             {
-                return GetRegistered(type)
-                    .FirstOrDefault(x => x.IsAttached && x.OwnerType.Name == parts[0] && x.Name == parts[1]);
+                yield return type.Name;
+                type = type.GetTypeInfo().BaseType;
             }
         }
+
         /// <summary>
         /// Checks whether a <see cref="PerspexProperty"/> is registered on a type.
         /// </summary>

+ 98 - 0
tests/Perspex.Base.UnitTests/PerspexPropertyRegistryTests.cs

@@ -46,6 +46,94 @@ namespace Perspex.Base.UnitTests
             Assert.Equal(new[] { "Attached" }, names);
         }
 
+        [Fact]
+        public void FindRegistered_Finds_Untyped_Property()
+        {
+            var result = PerspexPropertyRegistry.Instance.FindRegistered(typeof(Class1), "Foo");
+
+            Assert.Equal(Class1.FooProperty, result);
+        }
+
+        [Fact]
+        public void FindRegistered_Finds_Typed_Property()
+        {
+            var result = PerspexPropertyRegistry.Instance.FindRegistered(typeof(Class1), "Class1.Foo");
+
+            Assert.Equal(Class1.FooProperty, result);
+        }
+
+        [Fact]
+        public void FindRegistered_Finds_Typed_Inherited_Property()
+        {
+            var result = PerspexPropertyRegistry.Instance.FindRegistered(typeof(Class2), "Class1.Foo");
+
+            Assert.Equal(Class2.FooProperty, result);
+        }
+
+        [Fact]
+        public void FindRegistered_Finds_Inherited_Property_With_Derived_Type_Name()
+        {
+            var result = PerspexPropertyRegistry.Instance.FindRegistered(typeof(Class2), "Class2.Foo");
+
+            Assert.Equal(Class2.FooProperty, result);
+        }
+
+        [Fact]
+        public void FindRegistered_Finds_Attached_Property()
+        {
+            var result = PerspexPropertyRegistry.Instance.FindRegistered(typeof(Class2), "AttachedOwner.Attached");
+
+            Assert.Equal(AttachedOwner.AttachedProperty, result);
+        }
+
+        [Fact]
+        public void FindRegistered_Finds_AddOwnered_Untyped_Attached_Property()
+        {
+            var result = PerspexPropertyRegistry.Instance.FindRegistered(typeof(Class3), "Attached");
+
+            Assert.Equal(AttachedOwner.AttachedProperty, result);
+        }
+
+        [Fact]
+        public void FindRegistered_Finds_AddOwnered_Typed_Attached_Property()
+        {
+            var result = PerspexPropertyRegistry.Instance.FindRegistered(typeof(Class3), "Class3.Attached");
+
+            Assert.Equal(AttachedOwner.AttachedProperty, result);
+        }
+
+        [Fact]
+        public void FindRegistered_Finds_AddOwnered_AttachedTyped_Attached_Property()
+        {
+            var result = PerspexPropertyRegistry.Instance.FindRegistered(typeof(Class3), "AttachedOwner.Attached");
+
+            Assert.Equal(AttachedOwner.AttachedProperty, result);
+        }
+
+        [Fact]
+        public void FindRegistered_Finds_AddOwnered_BaseTyped_Attached_Property()
+        {
+            var result = PerspexPropertyRegistry.Instance.FindRegistered(typeof(Class3), "Class1.Attached");
+
+            Assert.Equal(AttachedOwner.AttachedProperty, result);
+        }
+
+        [Fact]
+        public void FindRegistered_Doesnt_Find_Nonregistered_Property()
+        {
+            var result = PerspexPropertyRegistry.Instance.FindRegistered(typeof(Class1), "Bar");
+
+            Assert.Null(result);
+        }
+
+        [Fact]
+        public void FindRegistered_Doesnt_Find_Nonregistered_Attached_Property()
+        {
+            var result = PerspexPropertyRegistry.Instance.FindRegistered(typeof(Class4), "AttachedOwner.Attached");
+
+            Assert.Null(result);
+        }
+
         private class Class1 : PerspexObject
         {
             public static readonly PerspexProperty<string> FooProperty =
@@ -70,6 +158,16 @@ namespace Perspex.Base.UnitTests
                 PerspexProperty.Register<Class2, double?>("Fred");
         }
 
+        private class Class3 : Class1
+        {
+            public static readonly PerspexProperty<string> AttachedProperty =
+                AttachedOwner.AttachedProperty.AddOwner<Class3>();
+        }
+
+        public class Class4 : PerspexObject
+        {
+        }
+
         private class AttachedOwner
         {
             public static readonly PerspexProperty<string> AttachedProperty =