PageRenderTime 25ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/Blocks/Configuration/Src/Design/Validation/DefaultPropertyValidator.cs

#
C# | 200 lines | 162 code | 28 blank | 10 comment | 31 complexity | 3489480b21b81e8e02a6bd67d2bfd445 MD5 | raw file
  1. //===============================================================================
  2. // Microsoft patterns & practices Enterprise Library
  3. // Core
  4. //===============================================================================
  5. // Copyright Š Microsoft Corporation. All rights reserved.
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
  7. // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
  8. // LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  9. // FITNESS FOR A PARTICULAR PURPOSE.
  10. //===============================================================================
  11. using System;
  12. using System.Collections.Generic;
  13. using System.Configuration;
  14. using System.Linq;
  15. using Microsoft.Practices.EnterpriseLibrary.Configuration.Design.Properties;
  16. using Microsoft.Practices.EnterpriseLibrary.Configuration.Design.ViewModel;
  17. using System.ComponentModel;
  18. using System.Globalization;
  19. namespace Microsoft.Practices.EnterpriseLibrary.Configuration.Design.Validation
  20. {
  21. internal class DefaultPropertyValidator : PropertyValidator
  22. {
  23. protected override void ValidateCore(Property property, string value, IList<ValidationResult> results)
  24. {
  25. object convertedValue = null;
  26. if (TryGetConvertedValue(property, value, results, out convertedValue))
  27. {
  28. var validators = GetConfigurationPropertyValidators(property)
  29. .Union(GetConfigurationValidators(property));
  30. foreach (var validator in validators)
  31. {
  32. validator.Validate(property, value, results);
  33. }
  34. }
  35. }
  36. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
  37. private static bool TryGetConvertedValue(Property property, string value, IList<ValidationResult> errors, out object convertedValue)
  38. {
  39. convertedValue = null;
  40. try
  41. {
  42. convertedValue = property.ConvertFromBindableValue(value);
  43. return true;
  44. }
  45. catch (Exception ex)
  46. {
  47. errors.Add(new PropertyValidationResult(property, ex.Message));
  48. }
  49. return false;
  50. }
  51. private static IEnumerable<Validator> GetConfigurationValidators(Property property)
  52. {
  53. var configurationValidators = property.Attributes
  54. .OfType<ConfigurationValidatorAttribute>()
  55. .Select(v => new ConfigurationValidatorWrappingValidator(v.ValidatorInstance));
  56. return configurationValidators.Cast<Validator>();
  57. }
  58. private IEnumerable<Validator> GetConfigurationPropertyValidators(Property property)
  59. {
  60. var configurationPropertyAttribute = property.Attributes.OfType<ConfigurationPropertyAttribute>().FirstOrDefault();
  61. if (configurationPropertyAttribute == null) yield break;
  62. if (configurationPropertyAttribute.IsRequired)
  63. {
  64. yield return new RequiredFieldValidator();
  65. }
  66. if (configurationPropertyAttribute.IsKey)
  67. {
  68. yield return new UniqueCollectionElementValidator();
  69. }
  70. }
  71. private class UniqueCollectionElementValidator : Validator
  72. {
  73. protected override void ValidateCore(object instance, string value, IList<ValidationResult> results)
  74. {
  75. var property = instance as ElementProperty;
  76. if (property == null) return;
  77. if (!IsKeyItem(property)) return;
  78. var containingElement = property.DeclaringElement as CollectionElementViewModel;
  79. if (containingElement == null) return;
  80. var parentCollection = containingElement.ParentElement as ElementCollectionViewModel;
  81. var newItemComparer = CreateMatchKeyPredicate(containingElement, property);
  82. if ((typeof(KeyValueConfigurationElement) == containingElement.ConfigurationElement.GetType()))
  83. {
  84. int itemCount = 0;
  85. foreach (var element in parentCollection.ChildElements)
  86. {
  87. if (string.Compare(value, (string)element.NameProperty.Value, StringComparison.OrdinalIgnoreCase) == 0)
  88. {
  89. itemCount++;
  90. }
  91. }
  92. if (itemCount > 1)
  93. {
  94. results.Add(new PropertyValidationResult(property, Resources.ValidationErrorDuplicateKeyValue));
  95. return;
  96. }
  97. }
  98. else
  99. {
  100. foreach (var element in parentCollection.ChildElements.OfType<CollectionElementViewModel>())
  101. {
  102. if (element.ElementId == containingElement.ElementId) { continue; }
  103. if (newItemComparer(element))
  104. {
  105. results.Add(new PropertyValidationResult(property, Resources.ValidationErrorDuplicateKeyValue));
  106. return;
  107. }
  108. }
  109. }
  110. }
  111. private static bool IsKeyItem(ElementProperty property)
  112. {
  113. var configPropertyAttribute = property.Attributes.OfType<ConfigurationPropertyAttribute>().FirstOrDefault();
  114. return (configPropertyAttribute != null && configPropertyAttribute.IsKey == true);
  115. }
  116. private static Func<ElementViewModel, bool> CreateMatchKeyPredicate(ElementViewModel elementBeingValidated, Property propertyBeingValidated)
  117. {
  118. string[] keyPropertyNames = elementBeingValidated.ConfigurationElement.
  119. ElementInformation.Properties.
  120. Cast<PropertyInformation>().
  121. Where(x => x.IsKey).
  122. Select(x => x.Name).ToArray();
  123. return otherElementInKeyComparison =>
  124. {
  125. foreach (string keyProperty in keyPropertyNames)
  126. {
  127. BindableProperty otherElementInKeyComparisonBindableProperty = otherElementInKeyComparison.Properties.OfType<ElementProperty>().Where(y => y.ConfigurationName == keyProperty).Single().BindableProperty;
  128. BindableProperty propertyOnElementBeingValidatedBindable = elementBeingValidated.Properties.OfType<ElementProperty>().Where(y=>y.ConfigurationName == keyProperty).Single().BindableProperty;
  129. if (!otherElementInKeyComparisonBindableProperty.IsBindableValueCommitted)
  130. {
  131. return false;
  132. }
  133. if (propertyOnElementBeingValidatedBindable.Property != propertyBeingValidated && !propertyOnElementBeingValidatedBindable.IsBindableValueCommitted)
  134. {
  135. return false;
  136. }
  137. if (!string.Equals(otherElementInKeyComparisonBindableProperty.BindableValue, propertyOnElementBeingValidatedBindable.BindableValue, StringComparison.OrdinalIgnoreCase))
  138. {
  139. return false;
  140. }
  141. }
  142. return true;
  143. };
  144. }
  145. }
  146. private class ConfigurationValidatorWrappingValidator : Validator
  147. {
  148. private ConfigurationValidatorBase validatorInstance;
  149. public ConfigurationValidatorWrappingValidator(ConfigurationValidatorBase validatorInstance)
  150. {
  151. this.validatorInstance = validatorInstance;
  152. }
  153. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
  154. protected override void ValidateCore(object instance, string value, IList<ValidationResult> results)
  155. {
  156. var property = instance as ElementProperty;
  157. if (property == null) return;
  158. if (validatorInstance.CanValidate(property.PropertyType))
  159. {
  160. try
  161. {
  162. validatorInstance.Validate(value);
  163. }
  164. catch (Exception ex)
  165. {
  166. results.Add(new PropertyValidationResult(property, ex.Message));
  167. }
  168. }
  169. }
  170. }
  171. }
  172. }