From 5872ece3ddc42d27e84df3eae24ef6fba5903d01 Mon Sep 17 00:00:00 2001 From: cneuwirt Date: Sun, 2 Dec 2007 14:27:54 +0000 Subject: [PATCH] Added ability to order the execution of dictionary adapter behaviors. git-svn-id: https://svn.castleproject.org/svn/castle/trunk@4553 73e77b4c-caa6-f847-a29a-24ab75ae54b6 --- .../DictionaryAdapterPropertyBinderAttribute.cs | 4 +- .../DictionaryBehaviorAttribute.cs} | 19 +++--- .../Attributes/DictionaryComponentAttribute.cs | 2 +- .../Attributes/DictionaryKeyAttribute.cs | 2 +- .../Attributes/DictionaryKeyPrefixAttribute.cs | 2 +- .../DictionaryKeySubstitutionAttribute.cs | 2 +- .../Attributes/DictionaryStringListAttribute.cs | 2 +- .../Attributes/DictionaryStringValuesAttribute.cs | 2 +- ...stle.Components.DictionaryAdapter-vs2005.csproj | 3 + .../DefaultPropertyGetter.cs | 8 +++ .../DictionaryAdapterFactory.cs | 40 +++++++++---- ...yAttribute.cs => DictionaryBehaviorComparer.cs} | 33 ++++++----- ...tionaryKeyBuilder.cs => IDictionaryBehavior.cs} | 15 ++--- .../IDictionaryKeyBuilder.cs | 2 +- .../IDictionaryPropertyGetter.cs | 2 +- .../IDictionaryPropertySetter.cs | 2 +- .../PropertyDescriptor.cs | 67 ++++++++++++---------- 17 files changed, 119 insertions(+), 88 deletions(-) copy Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/{IDictionaryKeyBuilder.cs => Attributes/DictionaryBehaviorAttribute.cs} (61%) copy Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/{Attributes/DictionaryKeyAttribute.cs => DictionaryBehaviorComparer.cs} (51%) copy Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/{IDictionaryKeyBuilder.cs => IDictionaryBehavior.cs} (60%) diff --git a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryAdapterPropertyBinderAttribute.cs b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryAdapterPropertyBinderAttribute.cs index 2e47ad7b9..28e6f17fd 100644 --- a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryAdapterPropertyBinderAttribute.cs +++ b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryAdapterPropertyBinderAttribute.cs @@ -22,8 +22,8 @@ namespace Castle.Components.DictionaryAdapter /// Allows the user to convert the values in the dictionary into a different type on access. /// [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] - public class DictionaryAdapterPropertyBinderAttribute : - Attribute, IDictionaryPropertyGetter, IDictionaryPropertySetter + public class DictionaryAdapterPropertyBinderAttribute : + DictionaryBehaviorAttribute, IDictionaryPropertyGetter, IDictionaryPropertySetter { private readonly DictionaryAdapterPropertyBinder binder; diff --git a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/IDictionaryKeyBuilder.cs b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryBehaviorAttribute.cs similarity index 61% copy from Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/IDictionaryKeyBuilder.cs copy to Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryBehaviorAttribute.cs index eaf0fc8fc..fac514e25 100644 --- a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/IDictionaryKeyBuilder.cs +++ b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryBehaviorAttribute.cs @@ -15,20 +15,21 @@ namespace Castle.Components.DictionaryAdapter { using System; - using System.Collections; /// - /// Defines the contract for building typed dictionary keys. + /// Assignes a specific dictionary key. /// - public interface IDictionaryKeyBuilder + public abstract class DictionaryBehaviorAttribute : Attribute, IDictionaryBehavior { + private int executionOrder = int.MaxValue; + /// - /// Builds the specified key. + /// Determines relative order to apply related behaviors. /// - /// The dictionary. - /// The current key. - /// The property. - /// The updated key - String GetKey(IDictionary dictionary, String key, PropertyDescriptor property); + public int ExecutionOrder + { + get { return executionOrder; } + set { executionOrder = value; } + } } } \ No newline at end of file diff --git a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryComponentAttribute.cs b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryComponentAttribute.cs index 9a2339a57..39e1e2d7a 100644 --- a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryComponentAttribute.cs +++ b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryComponentAttribute.cs @@ -22,7 +22,7 @@ namespace Castle.Components.DictionaryAdapter /// [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] public class DictionaryComponentAttribute : - Attribute, IDictionaryKeyBuilder, IDictionaryPropertyGetter + DictionaryBehaviorAttribute, IDictionaryKeyBuilder, IDictionaryPropertyGetter { private String prefix; diff --git a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryKeyAttribute.cs b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryKeyAttribute.cs index b49c72431..3bd4c1e3f 100644 --- a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryKeyAttribute.cs +++ b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryKeyAttribute.cs @@ -21,7 +21,7 @@ namespace Castle.Components.DictionaryAdapter /// Assignes a specific dictionary key. /// [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] - public class DictionaryKeyAttribute : Attribute, IDictionaryKeyBuilder + public class DictionaryKeyAttribute : DictionaryBehaviorAttribute, IDictionaryKeyBuilder { private readonly String key; diff --git a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryKeyPrefixAttribute.cs b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryKeyPrefixAttribute.cs index ff129f86f..afa119be6 100644 --- a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryKeyPrefixAttribute.cs +++ b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryKeyPrefixAttribute.cs @@ -21,7 +21,7 @@ namespace Castle.Components.DictionaryAdapter /// Assigns a prefix to the keyed properties of an interface. /// [AttributeUsage(AttributeTargets.Interface, AllowMultiple = false, Inherited = true)] - public class DictionaryKeyPrefixAttribute : Attribute, IDictionaryKeyBuilder + public class DictionaryKeyPrefixAttribute : DictionaryBehaviorAttribute, IDictionaryKeyBuilder { private String keyPrefix; diff --git a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryKeySubstitutionAttribute.cs b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryKeySubstitutionAttribute.cs index f8f342929..24070b223 100644 --- a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryKeySubstitutionAttribute.cs +++ b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryKeySubstitutionAttribute.cs @@ -21,7 +21,7 @@ namespace Castle.Components.DictionaryAdapter /// Substitutes part of key with another string. /// [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Property, AllowMultiple = true, Inherited = true)] - public class DictionaryKeySubstitutionAttribute : Attribute, IDictionaryKeyBuilder + public class DictionaryKeySubstitutionAttribute : DictionaryBehaviorAttribute, IDictionaryKeyBuilder { private readonly String oldValue; private readonly String newValue; diff --git a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryStringListAttribute.cs b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryStringListAttribute.cs index 7bae7b0c6..c7ef5c3bd 100644 --- a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryStringListAttribute.cs +++ b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryStringListAttribute.cs @@ -25,7 +25,7 @@ namespace Castle.Components.DictionaryAdapter /// delimited string value. /// [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] - public class DictionaryStringListAttribute : Attribute, + public class DictionaryStringListAttribute : DictionaryBehaviorAttribute, IDictionaryPropertyGetter, IDictionaryPropertySetter { diff --git a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryStringValuesAttribute.cs b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryStringValuesAttribute.cs index 1a7b10374..99eaa60f8 100644 --- a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryStringValuesAttribute.cs +++ b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryStringValuesAttribute.cs @@ -23,7 +23,7 @@ namespace Castle.Components.DictionaryAdapter /// [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Property, AllowMultiple = false, Inherited = true)] - public class DictionaryStringValuesAttribute : Attribute, IDictionaryPropertySetter + public class DictionaryStringValuesAttribute : DictionaryBehaviorAttribute, IDictionaryPropertySetter { private string format; diff --git a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Castle.Components.DictionaryAdapter-vs2005.csproj b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Castle.Components.DictionaryAdapter-vs2005.csproj index efa524824..fdfa8db7b 100644 --- a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Castle.Components.DictionaryAdapter-vs2005.csproj +++ b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Castle.Components.DictionaryAdapter-vs2005.csproj @@ -37,9 +37,12 @@ + + + diff --git a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/DefaultPropertyGetter.cs b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/DefaultPropertyGetter.cs index 5c3c002be..e2746a505 100644 --- a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/DefaultPropertyGetter.cs +++ b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/DefaultPropertyGetter.cs @@ -35,6 +35,14 @@ namespace Castle.Components.DictionaryAdapter } /// + /// + /// + public int ExecutionOrder + { + get { return int.MaxValue; } + } + + /// /// Gets the effective dictionary value. /// /// The dictionary factory. diff --git a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/DictionaryAdapterFactory.cs b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/DictionaryAdapterFactory.cs index 5fd3382af..1ae915bf9 100644 --- a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/DictionaryAdapterFactory.cs +++ b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/DictionaryAdapterFactory.cs @@ -418,28 +418,24 @@ namespace Castle.Components.DictionaryAdapter { Dictionary propertyMap = new Dictionary(); - ICollection typeGetters = - AttributesUtil.GetTypeAttributes(type); + ICollection typeGetters = + GetOrderedBehaviors(type); ICollection typeSetters = - AttributesUtil.GetTypeAttributes(type); + GetOrderedBehaviors(type); RecursivelyDiscoverProperties( type, delegate(PropertyInfo property) { PropertyDescriptor descriptor = new PropertyDescriptor(property); - descriptor.AddKeyBuilders( - AttributesUtil.GetAttributes(property)); - descriptor.AddKeyBuilders( - AttributesUtil.GetTypeAttributes(property.ReflectedType)); + descriptor.AddKeyBuilders(GetOrderedBehaviors(property)); + descriptor.AddKeyBuilders(GetOrderedBehaviors(property.ReflectedType)); - descriptor.AddGetters( - AttributesUtil.GetAttributes(property)); + descriptor.AddGetters(GetOrderedBehaviors(property)); descriptor.AddGetters(typeGetters); - AddDefaultGetter(descriptor); + AddDefaultGetter(descriptor); - descriptor.AddSetters( - AttributesUtil.GetAttributes(property)); + descriptor.AddSetters(GetOrderedBehaviors(property)); descriptor.AddSetters(typeSetters); propertyMap.Add(property.Name, descriptor); @@ -448,6 +444,26 @@ namespace Castle.Components.DictionaryAdapter return propertyMap; } + private static List GetOrderedBehaviors(Type type) where T : IDictionaryBehavior + { + List behaviors = AttributesUtil.GetTypeAttributes(type); + if (behaviors != null) + { + behaviors.Sort(DictionaryBehaviorComparer.Instance); + } + return behaviors; + } + + private static List GetOrderedBehaviors(MemberInfo member) where T : IDictionaryBehavior + { + List behaviors = AttributesUtil.GetAttributes(member); + if (behaviors != null) + { + behaviors.Sort(DictionaryBehaviorComparer.Instance); + } + return behaviors; + } + private static void RecursivelyDiscoverProperties( Type currentType, Action onProperty) { diff --git a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryKeyAttribute.cs b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/DictionaryBehaviorComparer.cs similarity index 51% copy from Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryKeyAttribute.cs copy to Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/DictionaryBehaviorComparer.cs index b49c72431..cc9fe5425 100644 --- a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/Attributes/DictionaryKeyAttribute.cs +++ b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/DictionaryBehaviorComparer.cs @@ -14,30 +14,33 @@ namespace Castle.Components.DictionaryAdapter { - using System; - using System.Collections; + using System.Collections.Generic; /// - /// Assignes a specific dictionary key. + /// Comparer for ordering the execution of /// - [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] - public class DictionaryKeyAttribute : Attribute, IDictionaryKeyBuilder + public class DictionaryBehaviorComparer : IComparer + where T : IDictionaryBehavior { - private readonly String key; - /// - /// Initializes a new instance of the class. + /// Singleton instance of /// - /// The key. - public DictionaryKeyAttribute(String key) - { - this.key = key; + public static readonly DictionaryBehaviorComparer + Instance = new DictionaryBehaviorComparer(); + + private DictionaryBehaviorComparer() + { } - String IDictionaryKeyBuilder.GetKey(IDictionary dictionary, String key, - PropertyDescriptor property) + /// + /// Determines the relative ordering of the behaviors. + /// + /// + /// + /// + public int Compare(T x, T y) { - return this.key; + return x.ExecutionOrder - y.ExecutionOrder; } } } \ No newline at end of file diff --git a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/IDictionaryKeyBuilder.cs b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/IDictionaryBehavior.cs similarity index 60% copy from Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/IDictionaryKeyBuilder.cs copy to Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/IDictionaryBehavior.cs index eaf0fc8fc..00348cdf8 100644 --- a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/IDictionaryKeyBuilder.cs +++ b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/IDictionaryBehavior.cs @@ -14,21 +14,14 @@ namespace Castle.Components.DictionaryAdapter { - using System; - using System.Collections; - /// - /// Defines the contract for building typed dictionary keys. + /// Defines the contract for customizing dictionary access. /// - public interface IDictionaryKeyBuilder + public interface IDictionaryBehavior { /// - /// Builds the specified key. + /// Determines relative order to apply related behaviors. /// - /// The dictionary. - /// The current key. - /// The property. - /// The updated key - String GetKey(IDictionary dictionary, String key, PropertyDescriptor property); + int ExecutionOrder { get; } } } \ No newline at end of file diff --git a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/IDictionaryKeyBuilder.cs b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/IDictionaryKeyBuilder.cs index eaf0fc8fc..723ea9d0b 100644 --- a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/IDictionaryKeyBuilder.cs +++ b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/IDictionaryKeyBuilder.cs @@ -20,7 +20,7 @@ namespace Castle.Components.DictionaryAdapter /// /// Defines the contract for building typed dictionary keys. /// - public interface IDictionaryKeyBuilder + public interface IDictionaryKeyBuilder : IDictionaryBehavior { /// /// Builds the specified key. diff --git a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/IDictionaryPropertyGetter.cs b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/IDictionaryPropertyGetter.cs index b89ca2ea1..53d37d14d 100644 --- a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/IDictionaryPropertyGetter.cs +++ b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/IDictionaryPropertyGetter.cs @@ -19,7 +19,7 @@ namespace Castle.Components.DictionaryAdapter /// /// Defines the contract for retrieving dictionary values. /// - public interface IDictionaryPropertyGetter + public interface IDictionaryPropertyGetter : IDictionaryBehavior { /// /// Gets the effective dictionary value. diff --git a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/IDictionaryPropertySetter.cs b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/IDictionaryPropertySetter.cs index 76590c053..d8db28465 100644 --- a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/IDictionaryPropertySetter.cs +++ b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/IDictionaryPropertySetter.cs @@ -19,7 +19,7 @@ namespace Castle.Components.DictionaryAdapter /// /// Defines the contract for updating dictionary values. /// - public interface IDictionaryPropertySetter + public interface IDictionaryPropertySetter : IDictionaryBehavior { /// /// Sets the stored dictionary value. diff --git a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/PropertyDescriptor.cs b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/PropertyDescriptor.cs index 30038c867..10c706a1f 100644 --- a/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/PropertyDescriptor.cs +++ b/Components/DictionaryAdapter/Castle.Components.DictionaryAdapter/PropertyDescriptor.cs @@ -28,9 +28,9 @@ namespace Castle.Components.DictionaryAdapter IDictionaryPropertySetter { private readonly PropertyInfo property; - private ICollection getters; - private ICollection setters; - private ICollection keyBuilders; + private List getters; + private List setters; + private List keyBuilders; private TypeConverter typeConverter; /// @@ -56,6 +56,14 @@ namespace Castle.Components.DictionaryAdapter } /// + /// + /// + public int ExecutionOrder + { + get { return 0; } + } + + /// /// Gets the property name. /// public string PropertyName @@ -113,7 +121,6 @@ namespace Castle.Components.DictionaryAdapter public ICollection KeyBuilders { get { return keyBuilders; } - set { keyBuilders = value; } } /// @@ -123,7 +130,6 @@ namespace Castle.Components.DictionaryAdapter public ICollection Setters { get { return setters; } - set { setters = value; } } /// @@ -133,7 +139,6 @@ namespace Castle.Components.DictionaryAdapter public ICollection Getters { get { return getters; } - set { getters = value; } } #region IDictionaryKeyBuilder Members @@ -183,15 +188,15 @@ namespace Castle.Components.DictionaryAdapter /// The builders. public void AddKeyBuilders(ICollection builders) { - if (keyBuilders == null) + if (builders != null) { - keyBuilders = builders; - } - else if (builders != null) - { - foreach(IDictionaryKeyBuilder builder in builders) + if (keyBuilders == null) { - keyBuilders.Add(builder); + keyBuilders = new List(builders); + } + else + { + keyBuilders.AddRange(builders); } } } @@ -250,15 +255,15 @@ namespace Castle.Components.DictionaryAdapter /// The getters. public void AddGetters(ICollection gets) { - if (getters == null) + if (gets != null) { - getters = gets; - } - else if (gets != null) - { - foreach(IDictionaryPropertyGetter getter in gets) + if (getters == null) { - getters.Add(getter); + getters = new List(gets); + } + else + { + getters.AddRange(gets); } } } @@ -280,6 +285,8 @@ namespace Castle.Components.DictionaryAdapter IDictionaryAdapterFactory factory, IDictionary dictionary, string key, ref object value, PropertyDescriptor descriptor) { + bool consumed = false; + if (setters != null) { foreach(IDictionaryPropertySetter setter in setters) @@ -287,7 +294,7 @@ namespace Castle.Components.DictionaryAdapter if (!setter.SetPropertyValue( factory, dictionary, key, ref value, this)) { - return false; + consumed = true; } } } @@ -297,11 +304,11 @@ namespace Castle.Components.DictionaryAdapter if (!descriptor.SetPropertyValue( factory, dictionary, key, ref value, null)) { - return false; + consumed = true; } } - return true; + return !consumed; } /// @@ -323,15 +330,15 @@ namespace Castle.Components.DictionaryAdapter /// The setters. public void AddSetters(ICollection sets) { - if (setters == null) - { - setters = sets; - } - else if (sets != null) + if (sets != null) { - foreach(IDictionaryPropertySetter setter in sets) + if (setters == null) + { + setters = new List(sets); + } + else { - setters.Add(setter); + setters.AddRange(sets); } } } -- 2.11.4.GIT