/// <summary> /// Gets all static rules defined on the specified types. /// </summary> /// <param name="types"></param> /// <returns></returns> public static IEnumerable <Rule> GetRules(IEnumerable <Type> types) { // Fetch the set of rules declared on the specified types List <Rule> rules = new List <Rule>(); foreach (Type type in types .Where(type => type.IsClass) .SelectMany(type => type.BaseType.IsGenericType ? new Type[] { type, type.BaseType } : new Type[] { type })) { rules.AddRange( type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) .Where(field => typeof(IRuleProvider).IsAssignableFrom(field.FieldType)) .SelectMany(field => { IRuleProvider ruleProvider = (IRuleProvider)field.GetValue(null); if (ruleProvider != null) { return(ruleProvider.GetRules(type, field.Name)); } else { StackTrace stackTrace = new StackTrace(); List <MethodBase> callStackMethods = stackTrace.GetFrames() .Select(f => f.GetMethod()) .ToList(); Type currentType = callStackMethods.First().DeclaringType; callStackMethods.Reverse(); MethodBase ruleProviderCall = callStackMethods.FirstOrDefault(method => currentType != method.DeclaringType && typeof(IRuleProvider).IsAssignableFrom(method.DeclaringType)); if (ruleProviderCall != null) { string errorMessage = string.Format( "'{0}'.'{1}' is null, declared as a '{2}', and '{3}'.'{4}' is creating/accessing rules. As such, it appears that the '{2}' is still initializing and rules will not register properly. Please see the call stack.", type.Name, field.Name, typeof(IRuleProvider).Name, ruleProviderCall.DeclaringType.Name, ruleProviderCall.Name ); throw new ApplicationException(errorMessage); } } return(new Rule[] { }); }) .Where(rule => rule != null) ); // Ensure the error code has been set on all statically declared condition types foreach (ConditionType error in type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) .Where(field => typeof(ConditionType).IsAssignableFrom(field.FieldType)) .Select(field => { ConditionType error = (ConditionType)field.GetValue(null); if (error != null && error.Code == null) { error.Code = field.DeclaringType.Name + "." + field.Name; } return(error); })) { } } return(rules); }
/// <summary> /// Creates a new <see cref="Condition"/> based on the specified <see cref="ConditionType"/> /// and error message. /// </summary> /// <param name="error"></param> public Condition(ConditionType type, string message, object target, params string[] properties) { this.Type = type; this.Message = message; this.AddTarget(target, properties); }
internal void ClearCondition(ConditionType error) { conditions.Remove(error.Code); }
/// <summary> /// Creates a new <see cref="Condition"/> based on the specified <see cref="ConditionType"/>. /// </summary> /// <param name="error"></param> public Condition(ConditionType type, object target, params string[] properties) : this(type, type.Message, target, properties) { }