/// <summary> /// This code gets called on the first time this Object type is constructed /// </summary> void AddSharedBusinessRules() { lock (_LockObject) { if (!SharedValidationRules.RulesExistFor(this.GetType())) { ValidationRulesManager mgrValidation = SharedValidationRules.GetManager(this.GetType()); CharacterFormattingRulesManager mgrCharacterCasing = SharedCharacterFormattingRules.GetManager(this.GetType()); foreach (var propInfo in PclReflection.GetPropertiesInfo(this)) { foreach (var atr in propInfo.GetCustomAttributes <BaseValidatorAttribute>(false)) { mgrValidation.AddRule(atr.Create(propInfo.Name), propInfo.Name); } foreach (var atr in propInfo.GetCustomAttributes <CharacterFormattingAttribute>(false)) { mgrCharacterCasing.AddRule(propInfo.Name, atr.CharacterCasing, atr.RemoveSpace); } } AddSharedBusinessValidationRules(mgrValidation); AddSharedCharacterCasingFormattingRules(mgrCharacterCasing); } } }
/// <summary> /// Validation rule that checks if the target property specified in the ruleDescriptor meets the postal code rule for the specified property. /// </summary> /// <param name="target">The target instance.</param> /// <param name="ruleDescriptor">The ruleDescriptor of type <see cref="StateAbbreviationRuleDescriptor" />.</param> /// <returns><c>True</c> does the target property specified in the ruleDescriptor meet the postal code rule for the specified property; otherwise <c>false</c>.</returns> /// <exception cref="ArgumentException">wrong rule passed to ruleDescriptor</exception> /// <exception cref="NotSupportedException">Postal code validation rule can only be applied to String properties</exception> public static Boolean PostalCodeRule(Object target, RuleDescriptorBase ruleDescriptor) { var args = ruleDescriptor as PostCodeRuleDescriptor; if (args == null) { throw new ArgumentException($"Wrong rule passed to PostalCodeRule: {ruleDescriptor.GetType()}"); } if (args.ValidateForUnitedStatesOnly == ValidateUnitedStatesOnly.Yes) { var pi = PclReflection.GetPropertyInfo(target, "Country"); if (pi == null) { return(true); } if (Convert.ToString(pi.GetValue(target, null)) != "United States") { return(true); } } var objPi = PclReflection.GetPropertyInfo(target, args.PropertyName); if (objPi.PropertyType != typeof(String)) { throw new NotSupportedException("Postal code validation rule can only be applied to String properties"); } var postalCode = Convert.ToString(objPi.GetValue(target, null)).Trim(); if (args.RequiredEntry == RequiredEntry.Yes) { if (String.IsNullOrEmpty(postalCode)) { ruleDescriptor.BrokenRuleDescription = $"Postal code was null or empty but is a required field: {RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)}"; return(false); } } else { if (String.IsNullOrEmpty(postalCode)) { return(true); } } const String pattern = "^\\d{5}(-\\d{4})?$"; var brokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} did not match the required Zip Code pattern"; if (Regex.IsMatch(postalCode, pattern, RegexOptions.IgnoreCase)) { return(true); } ruleDescriptor.BrokenRuleDescription = brokenRuleDescription; return(false); }
/// <summary> /// Builds up a string containing each property and value in the class. The string displays the property name, property friendly name and property value. /// </summary> /// <typeparam name="T">Class Type</typeparam> /// <param name="instance">Instance of the class</param> /// <param name="delimiter">What delimiter do you want between each property? Defaults to comma; can pass others like Environment.NewLine, etc.</param> /// <param name="sortByPropertyName">If set to <c>SortByPropertyName.Yes</c> then output will be sorted by AuditAttribute.AuditSequence and then property name; otherwise no additional sorting is performed and properties; will be left in ordinal order.</param> /// <returns>A string containing each property name, friendly name and value, separated by the delimiter and optionally sorted by property name.</returns> public static String ClassToString <T>(T instance, String delimiter = GlobalConstants.DefaultDelimiter, SortByPropertyName sortByPropertyName = SortByPropertyName.Yes) { var sb = new StringBuilder(4096); var list = new List <SortablePropertyBasket>(); foreach (var propInfo in PclReflection.GetPropertiesInfo(instance)) { var auditAttributes = propInfo.GetCustomAttributes <AuditAttribute>(false); var auditAttributeList = new List <AuditAttribute>(auditAttributes); AuditAttribute auditAttribute = null; if (auditAttributeList.Count == 1) { auditAttribute = auditAttributeList[0]; } var auditSequence = 1; if (auditAttribute != null) { auditSequence = auditAttribute.AuditSequence; } if (propInfo.Name != "Item" && propInfo.Name != "ValidationErrors") { list.Add(propInfo.GetValue(instance, null) != null ? new SortablePropertyBasket(auditSequence, propInfo.Name, CamelCaseString.GetWords(propInfo.Name), propInfo.GetValue(instance, null).ToString()) : new SortablePropertyBasket(auditSequence, propInfo.Name, CamelCaseString.GetWords(propInfo.Name), Null)); } } if (list.Count > 0) { if (sortByPropertyName == SortByPropertyName.Yes) { list.Sort(); } foreach (var propertyBasket in list) { sb.Append(propertyBasket); sb.Append(delimiter); } if (sb.Length > delimiter.Length) { sb.Length -= delimiter.Length; } } else { sb.Append("Class has no properties"); } return(sb.ToString()); }
/// <summary> /// Validation rule that checks if the target property specified in the ruleDescriptor meets the state abbreviation rule for the specified property. /// </summary> /// <param name="target">The target instance.</param> /// <param name="ruleDescriptor">The ruleDescriptor of type <see cref="StateAbbreviationRuleDescriptor" />.</param> /// <returns><c>True</c> does the target property specified in the ruleDescriptor meets the state abbreviation rule for the specified property; otherwise <c>false</c>.</returns> /// <exception cref="ArgumentException">wrong rule passed to ruleDescriptor</exception> /// <exception cref="NotSupportedException">State abbreviation validation rule can only be applied to String properties</exception> public static Boolean StateAbbreviationRule(Object target, RuleDescriptorBase ruleDescriptor) { var args = ruleDescriptor as StateAbbreviationRuleDescriptor; if (args == null) { throw new ArgumentException($"Wrong rule passed to StateAbbreviationRule {ruleDescriptor.GetType()}"); } if (args.ValidateForUnitedStatesOnly == ValidateUnitedStatesOnly.Yes) { var pi = PclReflection.GetPropertyInfo(target, "Country"); if (pi == null) { return(true); } if (Convert.ToString(pi.GetValue(target, null)) != "United States") { return(true); } } var objPi = PclReflection.GetPropertyInfo(target, args.PropertyName); if (objPi.PropertyType != typeof(String)) { throw new NotSupportedException("State abbreviation validation rule can only be applied to String properties"); } var state = Convert.ToString(objPi.GetValue(target, null)); if (args.RequiredEntry == RequiredEntry.Yes) { if (String.IsNullOrEmpty(state)) { ruleDescriptor.BrokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} was null or empty but is a required field"; return(false); } } else { if (String.IsNullOrEmpty(state)) { return(true); } } if (StateAbbreviationValidator.CreateInstance().IsValid(state)) { return(true); } args.BrokenRuleDescription = $"The entered value {state} is not a valid state abbreviation"; return(false); }
/// <summary> /// Builds up a string containing each property and value in the class decorated with the AuditAttribute. The string displays the property name, property friendly name and property value. /// </summary> /// <typeparam name="T">Class Type</typeparam> /// <param name="instance">Instance of the class</param> /// <param name="defaultValue">If no class properties are decorated with the <see cref="AuditAttribute"/> then a single entry will be added to the dictionary that is named 'DefaultValue' and will have the value of defaultValue.</param> /// <param name="delimiter">What delimiter do you want between each property? Defaults to comma; can pass others like Environment.NewLine, etc.</param> /// <param name="includeAllProperties">if set to <c>true</c> [include all attributes].</param> /// <returns>A string containing each property name, friendly name and value, separated by the delimiter and sorted by AuditAttribute.AuditSequence and then property name.</returns> public static String AuditToString <T>(T instance, String defaultValue, String delimiter = GlobalConstants.DefaultDelimiter, Boolean includeAllProperties = false) { var sb = new StringBuilder(2048); var list = new List <SortablePropertyBasket>(); var nonAttributedPropertyIndex = 0; foreach (var propInfo in PclReflection.GetPropertiesInfo(instance)) { var auditAttributes = propInfo.GetCustomAttributes <AuditAttribute>(false); var auditAttributeList = new List <AuditAttribute>(auditAttributes); AuditAttribute auditAttribute = null; if (auditAttributeList.Count == 1) { auditAttribute = auditAttributeList[0]; } if (auditAttribute != null) { list.Add(propInfo.GetValue(instance, null) != null ? new SortablePropertyBasket(auditAttribute.AuditSequence, propInfo.Name, CamelCaseString.GetWords(propInfo.Name), propInfo.GetValue(instance, null).ToString()) : new SortablePropertyBasket(auditAttribute.AuditSequence, propInfo.Name, CamelCaseString.GetWords(propInfo.Name), Null)); } else if (includeAllProperties && propInfo.Name != "Item") { nonAttributedPropertyIndex += 1; list.Add(propInfo.GetValue(instance, null) != null ? new SortablePropertyBasket(nonAttributedPropertyIndex, propInfo.Name, CamelCaseString.GetWords(propInfo.Name), propInfo.GetValue(instance, null).ToString()) : new SortablePropertyBasket(nonAttributedPropertyIndex, propInfo.Name, CamelCaseString.GetWords(propInfo.Name), Null)); } } if (list.Count > 0) { list.Sort(); foreach (SortablePropertyBasket propertyBasket in list) { sb.Append(propertyBasket); sb.Append(delimiter); } if (sb.Length > delimiter.Length) { sb.Length -= delimiter.Length; } } else { sb.Append(defaultValue); } return(sb.ToString()); }
/// <summary> /// Validation rule that checks if the target property specified in the ruleDescriptor is equal to the other specified property. /// </summary> /// <param name="target">The target instance.</param> /// <param name="ruleDescriptor">The ruleDescriptor of type <see cref="ComparePasswordRuleDescriptor" />.</param> /// <returns><c>True</c> if the target property specified in the ruleDescriptor is equal to the other specified property, otherwise <c>false</c>.</returns> /// <exception cref="ArgumentNullException">target or ruleDescriptor is null.</exception> /// <exception cref="ArgumentException">Wrong rule passed to ComparePropertyRule</exception> public static Boolean ComparePasswordRule(Object target, RuleDescriptorBase ruleDescriptor) { if (target == null) { throw new ArgumentNullException(nameof(target)); } if (ruleDescriptor == null) { throw new ArgumentNullException(nameof(ruleDescriptor)); } var args = ruleDescriptor as ComparePasswordRuleDescriptor; if (args == null) { throw new ArgumentException($"Wrong rule passed to ComparePasswordRule {ruleDescriptor.GetType()}"); } PropertyInfo pi = PclReflection.GetPropertyInfo(target, args.PropertyName); var source = pi.GetValue(target, null); if (source == null) { return(true); } pi = PclReflection.GetPropertyInfo(target, args.CompareToPropertyName); var testAgainst = pi.GetValue(target, null); if (testAgainst == null) { return(true); } var iSource = (IComparable)source; var iTestAgainst = (IComparable)testAgainst; var result = iSource.CompareTo(iTestAgainst); if (result == 0) { return(true); } ruleDescriptor.BrokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} must be equal to {InputStringFormatting.CamelCaseString.GetWords(args.CompareToPropertyName)}."; return(false); }
/// <summary> /// Validation rule that checks if the target property specified in the ruleDescriptor meets the String length criteria for the specified property. /// </summary> /// <param name="target">The target instance.</param> /// <param name="ruleDescriptor">The ruleDescriptor of type <see cref="StringLengthRuleDescriptor" />.</param> /// <returns><c>True</c> is the target property specified in the ruleDescriptor meets the String length criteria for the specified property; otherwise <c>false</c>.</returns> /// <exception cref="ArgumentException">wrong rule passed to ruleDescriptor</exception> public static Boolean StringLengthRule(Object target, RuleDescriptorBase ruleDescriptor) { var args = ruleDescriptor as StringLengthRuleDescriptor; if (args == null) { throw new ArgumentException($"Wrong rule passed to StringLengthRule {ruleDescriptor.GetType()}"); } var objPi = PclReflection.GetPropertyInfo(target, args.PropertyName); var testMe = Convert.ToString(objPi.GetValue(target, null)); // ReSharper disable ConditionIsAlwaysTrueOrFalse if (args.AllowNullString == AllowNullString.No && (testMe == null)) { // ReSharper restore ConditionIsAlwaysTrueOrFalse ruleDescriptor.BrokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} can not be null"; return(false); } if (args.AllowNullString == AllowNullString.Yes && String.IsNullOrWhiteSpace(testMe)) { return(true); } if (String.IsNullOrEmpty(testMe)) { testMe = String.Empty; } if (args.MinimumLength > 0 && testMe.Length < args.MinimumLength) { ruleDescriptor.BrokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} can not be less than {args.MinimumLength} character's long"; return(false); } if (args.MaximumLength > 0 && testMe.Length > args.MaximumLength) { ruleDescriptor.BrokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} can not be greater than {args.MaximumLength} character's long"; return(false); } return(true); }
/// <summary> /// Validation rule that checks if the target property specified in the ruleDescriptor meets the domain rule. A domain in this case means an array of valid values. /// </summary> /// <param name="target">The target instance.</param> /// <param name="ruleDescriptor">The ruleDescriptor of type <see cref="DomainRuleDescriptor" />.</param> /// <returns><c>True</c> is the target property specified in the ruleDescriptor meets the domain rule, otherwise <c>false</c>.</returns> /// <exception cref="ArgumentNullException">target or ruleDescriptor was null.</exception> /// <exception cref="ArgumentException">If the ruleDescriptor is not of type <see cref="DomainRuleDescriptor" />.</exception> public static Boolean DomainRule(Object target, RuleDescriptorBase ruleDescriptor) { if (target == null) { throw new ArgumentNullException(nameof(target)); } if (ruleDescriptor == null) { throw new ArgumentNullException(nameof(ruleDescriptor)); } var args = ruleDescriptor as DomainRuleDescriptor; if (args == null) { throw new ArgumentException($"Wrong rule passed to DomainRule: {ruleDescriptor.GetType()}"); } PropertyInfo pi = PclReflection.GetPropertyInfo(target, args.PropertyName); String propertyValue = Convert.ToString(pi.GetValue(target, null)); if (args.RequiredEntry == RequiredEntry.No && String.IsNullOrEmpty(propertyValue)) { return(true); } if (args.Data.Any(s => String.Compare(s, propertyValue, StringComparison.OrdinalIgnoreCase) == 0)) { return(true); } var sb = new System.Text.StringBuilder(1024); sb.AppendFormat("The {0} did not match any of the following acceptable values.", RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)); const String format = ", {0}"; foreach (String s in args.Data) { sb.AppendFormat(format, s); } ruleDescriptor.BrokenRuleDescription = sb.ToString(); return(false); }
/// <summary> /// Populates the passed in IDictionary with property's name and value in the class for properties decorated with the <see cref="AuditAttribute"/>. /// </summary> /// <typeparam name="T">Class type.</typeparam> /// <param name="instance">The instance.</param> /// <param name="defaultValue">If no class properties are decorated with the <see cref="AuditAttribute"/> then a single entry will be added to the dictionary that is named 'DefaultValue' and will have the value of defaultValue.</param> /// <param name="dictionary">Pass an IDictionary object that needs to be populated. This could be the Data property of an exception object that you want to populate, etc.</param> /// <param name="sortByPropertyName">If set to <c>SortByPropertyName.Yes</c> then output will be sorted by AuditAttribute.AuditSequence and then property name; otherwise no additional sorting is performed and properties; will be left in ordinal order.</param> /// <returns>The dictionary passed in populated with properties and values.</returns> public static IDictionary <String, String> ClassToIDictionary <T>(T instance, String defaultValue, IDictionary <String, String> dictionary, SortByPropertyName sortByPropertyName = SortByPropertyName.Yes) { var list = new List <SortablePropertyBasket>(); foreach (var propInfo in PclReflection.GetPropertiesInfo(instance)) { var auditAttributes = propInfo.GetCustomAttributes <AuditAttribute>(false); var auditAttributeList = new List <AuditAttribute>(auditAttributes); AuditAttribute auditAttribute = null; if (auditAttributeList.Count == 1) { auditAttribute = auditAttributeList[0]; } if (auditAttribute != null) { list.Add(new SortablePropertyBasket(One, propInfo.Name, String.Empty, propInfo.GetValue(instance, null).ToString())); } } if (list.Count > 0) { if (sortByPropertyName == SortByPropertyName.Yes) { list.Sort(); } foreach (SortablePropertyBasket propertyBasket in list) { dictionary.Add(propertyBasket.PropertyName, propertyBasket.Value); } } else { dictionary.Add(DefaultValue, defaultValue); } return(dictionary); }
/// <summary> /// Populates the dictionary with property's name and value in the class for properties decorated with the <see cref="AuditAttribute"/>. /// </summary> /// <typeparam name="T">Class type.</typeparam> /// <param name="instance">The instance.</param> /// <param name="defaultValue">If no class properties are decorated with the <see cref="AuditAttribute"/> then a single entry will be added to the dictionary that is named 'DefaultValue' and will have the value of defaultValue.</param>. /// <param name="dictionary">Pass an IDictionary object that needs to be populated. This could be the Data property of an exception object that you want to populate, etc.</param> /// <returns>IDictionary populated with properties and values.</returns> public static IDictionary <String, String> AuditToIDictionary <T>(T instance, String defaultValue, IDictionary <String, String> dictionary) { var list = new List <SortablePropertyBasket>(); foreach (var propInfo in PclReflection.GetPropertiesInfo(instance)) { var auditAttributes = propInfo.GetCustomAttributes <AuditAttribute>(false); var auditAttributeList = new List <AuditAttribute>(auditAttributes); AuditAttribute auditAttribute = null; if (auditAttributeList.Count == 1) { auditAttribute = auditAttributeList[0]; } if (auditAttribute != null) { list.Add(new SortablePropertyBasket(auditAttribute.AuditSequence, propInfo.Name, CamelCaseString.GetWords(propInfo.Name), propInfo.GetValue(instance, null).ToString())); } } if (list.Count > 0) { list.Sort(); foreach (var propertyBasket in list) { dictionary.Add(propertyBasket.PropertyName, propertyBasket.Value); } } else { dictionary.Add(DefaultValue, defaultValue); } return(dictionary); }
/// <summary> /// Validation rule that checks if the target property specified in the ruleDescriptor is not null. /// </summary> /// <param name="target">The target instance.</param> /// <param name="ruleDescriptor">The ruleDescriptor of type <see cref="NotNullRuleDescriptor" />.</param> /// <returns><c>True</c> is the target property specified in the ruleDescriptor is not null, otherwise <c>false</c>.</returns> /// <exception cref="ArgumentNullException">Either target or ruleDescriptor is null.</exception> /// <exception cref="ArgumentException">If the ruleDescriptor is not of type <see cref="NotNullRuleDescriptor" />.</exception> public static Boolean NotNullRule(Object target, RuleDescriptorBase ruleDescriptor) { if (target == null) { throw new ArgumentNullException(nameof(target)); } if (ruleDescriptor == null) { throw new ArgumentNullException(nameof(ruleDescriptor)); } //Boxing and Unboxing //When a nullable type is boxed, the common language runtime automatically boxes the underlying value of the //Nullable Object, not the Nullable Object itself. That is, if the HasValue property is true, the contents //of the Value property is boxed. If the HasValue property is false, a null reference (Nothing in Visual Basic) is boxed. //When the underlying value of a nullable type is un-boxed, the common language runtime creates a new //Nullable structure initialized to the underlying value. var args = ruleDescriptor as NotNullRuleDescriptor; if (args == null) { throw new ArgumentException($"Wrong rule passed to NotNullRule {ruleDescriptor.GetType()}"); } PropertyInfo pi = PclReflection.GetPropertyInfo(target, args.PropertyName); Object source = pi.GetValue(target, null); //this handles both Nullable and standard uninitialized values if (source == null) { ruleDescriptor.BrokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} is null."; return(false); } return(true); }
/// <summary> /// Validation rule that checks if the target property specified in the ruleDescriptor meets the comparison criteria against another specified property. /// </summary> /// <param name="target">The target instance.</param> /// <param name="ruleDescriptor">The ruleDescriptor of type <see cref="ComparePropertyRuleDescriptor" />.</param> /// <returns><c>True</c> is the target property specified in the ruleDescriptor meets the comparison criteria against another specified property, otherwise <c>false</c>.</returns> /// <exception cref="ArgumentNullException">target or ruleDescriptor is null.</exception> /// <exception cref="ArgumentException">Wrong rule passed to ComparePropertyRule</exception> /// <exception cref="OverflowException">comparison type not programmed</exception> public static Boolean ComparePropertyRule(Object target, RuleDescriptorBase ruleDescriptor) { if (target == null) { throw new ArgumentNullException(nameof(target)); } if (ruleDescriptor == null) { throw new ArgumentNullException(nameof(ruleDescriptor)); } var args = ruleDescriptor as ComparePropertyRuleDescriptor; if (args == null) { throw new ArgumentException($"Wrong rule passed to ComparePropertyRule {ruleDescriptor.GetType()}"); } PropertyInfo pi = PclReflection.GetPropertyInfo(target, args.PropertyName); Object source = pi.GetValue(target, null); var stringSource = source as String; if (args.RequiredEntry == RequiredEntry.Yes) { if (source == null || (stringSource != null && String.IsNullOrWhiteSpace(stringSource))) { ruleDescriptor.BrokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} was null or empty but is a required field."; return(false); } } else { if (source == null) { return(true); } } pi = PclReflection.GetPropertyInfo(target, args.CompareToPropertyName); Object testAgainst = pi.GetValue(target, null); if (testAgainst == null) { return(true); } var iSource = (IComparable)source; var iTestAgainst = (IComparable)testAgainst; Int32 result = iSource.CompareTo(iTestAgainst); switch (args.ComparisonType) { case ComparisonType.Equal: if (result == 0) { return(true); } ruleDescriptor.BrokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} must be equal to {testAgainst}."; return(false); case ComparisonType.GreaterThan: if (result > 0) { return(true); } ruleDescriptor.BrokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} must be greater than {testAgainst}."; return(false); case ComparisonType.GreaterThanEqual: if (result >= 0) { return(true); } ruleDescriptor.BrokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} must be greater than or equal to {testAgainst}."; return(false); case ComparisonType.LessThan: if (result < 0) { return(true); } ruleDescriptor.BrokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} must be less than {testAgainst}."; return(false); case ComparisonType.LessThanEqual: if (result <= 0) { return(true); } ruleDescriptor.BrokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} must be less than or equal to {testAgainst}."; return(false); case ComparisonType.NotEqual: if (result != 0) { return(true); } ruleDescriptor.BrokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} must not equal {testAgainst}."; return(false); default: throw new OverflowException("comparison type not programmed"); } }
/// <summary> /// Validation rule that checks if the target property specified in the ruleDescriptor is within the specified range. /// </summary> /// <param name="target">The target instance.</param> /// <param name="ruleDescriptor">The ruleDescriptor of type <see cref="RangeRuleDescriptor" />.</param> /// <returns><c>True</c> is the target property specified in the ruleDescriptor is within the specified range, otherwise <c>false</c>.</returns> /// <exception cref="ArgumentNullException">target or ruleDescriptor is null.</exception> /// <exception cref="ArgumentException">Wrong rule passed to InRangeRule</exception> public static Boolean InRangeRule(Object target, RuleDescriptorBase ruleDescriptor) { if (target == null) { throw new ArgumentNullException(nameof(target)); } if (ruleDescriptor == null) { throw new ArgumentNullException(nameof(ruleDescriptor)); } var args = ruleDescriptor as RangeRuleDescriptor; if (args == null) { throw new ArgumentException($"Wrong rule passed to InRangeRule {ruleDescriptor.GetType()}"); } PropertyInfo pi = PclReflection.GetPropertyInfo(target, args.PropertyName); Object source = pi.GetValue(target, null); var stringSource = source as String; if (args.RequiredEntry == RequiredEntry.Yes) { if (source == null || (stringSource != null && String.IsNullOrWhiteSpace(stringSource))) { ruleDescriptor.BrokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} was null or empty but is a required field."; return(false); } } else { if (source == null) { return(true); } } var iSource = (IComparable)source; Object lower = args.LowerValue; Object upper = args.UpperValue; Int32 lowerResult = iSource.CompareTo(args.LowerValue); if (args.LowerRangeBoundaryType == RangeBoundaryType.Inclusive) { if (lowerResult < 0) { ruleDescriptor.BrokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} must be greater than or equal to {lower}"; return(false); } } else { if (lowerResult <= 0) { ruleDescriptor.BrokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} must be greater than {lower}"; return(false); } } Int32 upperResult = iSource.CompareTo(args.UpperValue); if (args.UpperRangeBoundaryType == RangeBoundaryType.Inclusive) { if (upperResult > 0) { ruleDescriptor.BrokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} must be less than {upper}"; return(false); } } else { if (upperResult >= 0) { ruleDescriptor.BrokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} must be less than or equal to {upper}"; return(false); } } return(true); }
/// <summary> /// Validation rule that checks if the target property specified in the ruleDescriptor meets the regular expression rule for the specified property. /// </summary> /// <param name="target">The target instance.</param> /// <param name="ruleDescriptor">The ruleDescriptor of type <see cref="RegularExpressionRuleDescriptor" />.</param> /// <returns><c>True</c> is the target property specified in the ruleDescriptor meets the state abbreviation rule for the specified property; otherwise <c>false</c>.</returns> /// <exception cref="ArgumentException">wrong rule passed to ruleDescriptor</exception> /// <exception cref="InvalidOperationException"> /// CustomRegularExpressionPattern not supplied /// or /// CustomRegularExpressionPattern is not a valid RegEx pattern. /// </exception> /// <exception cref="OverflowException">RegularExpressionPatternType type not programmed</exception> public static Boolean RegularExpressionRule(Object target, RuleDescriptorBase ruleDescriptor) { //great site for patterns //http://regexlib.com/Search.aspx // var args = ruleDescriptor as RegularExpressionRuleDescriptor; if (args == null) { throw new ArgumentException($"Wrong rule passed to RegularExpressionRule {ruleDescriptor.GetType()}"); } var objPi = PclReflection.GetPropertyInfo(target, args.PropertyName); var testMe = Convert.ToString(objPi.GetValue(target, null)); if (args.RegularExpressionPatternType == RegularExpressionPatternType.Custom && String.IsNullOrEmpty(args.CustomRegularExpressionPattern)) { throw new InvalidOperationException("CustomRegularExpressionPattern not supplied"); } if (!IsRegularExpressionPatternValid(args.CustomRegularExpressionPattern)) { throw new InvalidOperationException("CustomRegularExpressionPattern is not a valid RegEx pattern."); } if (args.RequiredEntry == RequiredEntry.Yes) { if (String.IsNullOrWhiteSpace(testMe)) { ruleDescriptor.BrokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} was null or empty but is a required field"; return(false); } } else { if (testMe.Trim().Length == 0) { return(true); } } String pattern; String brokenRuleDescription; switch (args.RegularExpressionPatternType) { case RegularExpressionPatternType.Custom: pattern = args.CustomRegularExpressionPattern; brokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} did not match the required {pattern} pattern"; break; case RegularExpressionPatternType.Email: pattern = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$"; brokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} did not match the required email pattern"; break; case RegularExpressionPatternType.IPAddress: pattern = "^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$"; brokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} did not match the required IP Address pattern"; break; case RegularExpressionPatternType.SSN: pattern = "^\\d{3}-\\d{2}-\\d{4}$"; brokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} did not match the required SSN pattern"; break; case RegularExpressionPatternType.Url: pattern = "(?#WebOrIP)((?#protocol)((news|nntp|telnet|http|ftp|https|ftps|sftp):\\/\\/)?(?#subDomain)(([a-zA-Z0-9]+\\.*(?#domain)[a-zA-Z0-9\\-]+(?#TLD)(\\.[a-zA-Z]+){1,2})|(?#IPAddress)((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])))+(?#Port)(:[1-9][0-9]*)?)+(?#Path)((\\/((?#dirOrFileName)[a-zA-Z0-9 \\-\\%\\~\\+]+)?)*)?(?#extension)(\\.([a-zA-Z0-9 ]+))?(?#parameters)(\\?([a-zA-Z0-9 \\-]+\\=[a-z-A-Z0-9 \\-\\%\\~\\+]+)?(?#additionalParameters)(\\&([a-zA-Z0-9 \\-]+\\=[a-z-A-Z0-9 \\-\\%\\~\\+]+)?)*)?"; brokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} did not match the required URL pattern"; break; case RegularExpressionPatternType.ZipCode: pattern = "^\\d{5}(-\\d{4})?$"; brokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} did not match the required Zip Code pattern"; break; default: throw new OverflowException("RegularExpressionPatternType type not programmed"); } if (Regex.IsMatch(testMe, pattern, RegexOptions.IgnoreCase)) { return(true); } ruleDescriptor.BrokenRuleDescription = brokenRuleDescription; return(false); }
/// <summary> /// Validation rule that checks if the target property specified in the ruleDescriptor meets the bank routing number rule for the specified property. /// </summary> /// <param name="target">The target instance.</param> /// <param name="ruleDescriptor">The ruleDescriptor of type <see cref="BankRoutingNumberRuleDescriptor" />.</param> /// <returns><c>True</c> is the target property specified in the ruleDescriptor meets the bank routing number rule for the specified property; otherwise <c>false</c>.</returns> /// <exception cref="ArgumentException">wrong rule passed to ruleDescriptor</exception> /// <exception cref="NotSupportedException">Bank routing number validation rule can only be applied to a String</exception> public static Boolean BankRoutingNumberRule(Object target, RuleDescriptorBase ruleDescriptor) { var args = ruleDescriptor as BankRoutingNumberRuleDescriptor; if (args == null) { throw new ArgumentException($"Wrong rule {ruleDescriptor.GetType()}, passed to BankRoutingNumberRule"); } var objPi = PclReflection.GetPropertyInfo(target, args.PropertyName); if (objPi.PropertyType != typeof(String)) { throw new NotSupportedException("Bank routing number validation rule can only be applied to a String"); } String bankRoutingNumber = Convert.ToString(objPi.GetValue(target, null)); if (args.RequiredEntry == RequiredEntry.Yes) { if (String.IsNullOrEmpty(bankRoutingNumber)) { ruleDescriptor.BrokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} null or empty but is a required field"; return(false); } } else { if (String.IsNullOrEmpty(bankRoutingNumber)) { return(true); } } var lengthBankRoutingNumber = bankRoutingNumber.Length; var value = 0; if (lengthBankRoutingNumber != 9) { args.BrokenRuleDescription = $"The entered value {bankRoutingNumber} is not a valid bank routing number. All bank routing numbers are 9 digit in length"; return(false); } if (Int32.Parse(bankRoutingNumber.Substring(0, 1)) > 1) { args.BrokenRuleDescription = $"The entered value {bankRoutingNumber} is not a valid bank routing number. The first digit must be a 0 or a 1"; return(false); } if (bankRoutingNumber.Cast <Char>().Any(c => !Char.IsDigit(c))) { args.BrokenRuleDescription = $"The entered value {bankRoutingNumber} is not a valid bank routing number. Only numeric input is allowed"; return(false); } for (var intX = 0; intX <= 8; intX += 3) { value += Int32.Parse(bankRoutingNumber.Substring(intX, 1)) * 3; value += Int32.Parse(bankRoutingNumber.Substring(intX + 1, 1)) * 7; value += Int32.Parse(bankRoutingNumber.Substring(intX + 2, 1)); } if (value % 10 != 0) { args.BrokenRuleDescription = $"The entered value {bankRoutingNumber} is not a valid bank routing number"; return(false); } return(true); }
/// <summary> /// Validation rule that checks if the target property specified in the ruleDescriptor meets the credit card number rule for the specified property. /// </summary> /// <param name="target">The target instance.</param> /// <param name="ruleDescriptor">The ruleDescriptor of type <see cref="CreditCardNumberRuleDescriptor" />.</param> /// <returns><c>True</c> is the target property specified in the ruleDescriptor meets the credit card number rule for the specified property; otherwise <c>false</c>.</returns> /// <exception cref="ArgumentException">wrong rule passed to ruleDescriptor</exception> /// <exception cref="NotSupportedException">Credit card number validation rule can only be applied to String properties</exception> public static Boolean CreditCardNumberRule(Object target, RuleDescriptorBase ruleDescriptor) { var args = ruleDescriptor as CreditCardNumberRuleDescriptor; if (args == null) { throw new ArgumentException($"Wrong rule passed to CreditCardNumberRule {ruleDescriptor.GetType()}"); } var objPi = PclReflection.GetPropertyInfo(target, args.PropertyName); if (objPi.PropertyType != typeof(String)) { throw new NotSupportedException("Credit card number validation rule can only be applied to String properties"); } var cardNumber = Convert.ToString(objPi.GetValue(target, null)); if (args.RequiredEntry == RequiredEntry.Yes) { if (String.IsNullOrEmpty(cardNumber)) { ruleDescriptor.BrokenRuleDescription = $"{RuleDescriptorBase.GetPropertyFriendlyName(ruleDescriptor)} was null or empty but is a required field"; return(false); } } else { if (String.IsNullOrEmpty(cardNumber)) { return(true); } } var lengthCreditCardNumber = cardNumber.Length; var cardArray = new Int32[lengthCreditCardNumber + 1]; Int32 value; if (cardNumber.Cast <Char>().Any(c => !Char.IsDigit(c))) { args.BrokenRuleDescription = $"The entered value {cardNumber} is not a valid credit card number. Only numeric input is allowed"; return(false); } for (var count = lengthCreditCardNumber - 1; count >= 1; count -= 2) { value = Convert.ToInt32(cardNumber.Substring(count - 1, 1)) * 2; cardArray[count] = value; } value = 0; var start = lengthCreditCardNumber % 2 == 0 ? 2 : 1; for (var count = start; count <= lengthCreditCardNumber; count += 2) { value = value + Convert.ToInt32(cardNumber.Substring(count - 1, 1)); var arrValue = cardArray[count - 1]; if (arrValue < 10) { value = value + arrValue; } else { value = value + Convert.ToInt32(Convert.ToString(arrValue).Substring(0, 1)) + Convert.ToInt32(Convert.ToString(arrValue).Substring(Convert.ToString(arrValue).Length - 1)); } } if (value % 10 != 0) { args.BrokenRuleDescription = $"The entered value {cardNumber} is not a valid credit card number"; return(false); } return(true); }