768 lines
28 KiB
C#
768 lines
28 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Csla.Validation
|
|
{
|
|
|
|
/// <summary>
|
|
/// Tracks the business rules broken within a business object.
|
|
/// </summary>
|
|
[Serializable()]
|
|
public class ValidationRules
|
|
{
|
|
// list of broken rules for this business object.
|
|
private BrokenRulesCollection _brokenRules;
|
|
// threshold for short-circuiting to kick in
|
|
private int _processThroughPriority;
|
|
// reference to current business object
|
|
[NonSerialized()]
|
|
private object _target;
|
|
// reference to per-instance rules manager for this object
|
|
[NonSerialized()]
|
|
private ValidationRulesManager _instanceRules;
|
|
// reference to per-type rules manager for this object
|
|
[NonSerialized()]
|
|
private ValidationRulesManager _typeRules;
|
|
// reference to the active set of rules for this object
|
|
[NonSerialized()]
|
|
private ValidationRulesManager _rulesToCheck;
|
|
|
|
internal ValidationRules(object businessObject)
|
|
{
|
|
SetTarget(businessObject);
|
|
}
|
|
|
|
internal void SetTarget(object businessObject)
|
|
{
|
|
_target = businessObject;
|
|
}
|
|
|
|
private BrokenRulesCollection BrokenRulesList
|
|
{
|
|
get
|
|
{
|
|
if (_brokenRules == null)
|
|
_brokenRules = new BrokenRulesCollection();
|
|
return _brokenRules;
|
|
}
|
|
}
|
|
|
|
private ValidationRulesManager GetInstanceRules(bool createObject)
|
|
{
|
|
if (_instanceRules == null)
|
|
if (createObject)
|
|
_instanceRules = new ValidationRulesManager();
|
|
return _instanceRules;
|
|
}
|
|
|
|
private ValidationRulesManager GetTypeRules(bool createObject)
|
|
{
|
|
if (_typeRules == null)
|
|
_typeRules = SharedValidationRules.GetManager(_target.GetType(), createObject);
|
|
return _typeRules;
|
|
}
|
|
|
|
private ValidationRulesManager RulesToCheck
|
|
{
|
|
get
|
|
{
|
|
if (_rulesToCheck == null)
|
|
{
|
|
ValidationRulesManager instanceRules = GetInstanceRules(false);
|
|
ValidationRulesManager typeRules = GetTypeRules(false);
|
|
if (instanceRules == null)
|
|
{
|
|
if (typeRules == null)
|
|
_rulesToCheck = null;
|
|
else
|
|
_rulesToCheck = typeRules;
|
|
}
|
|
else if (typeRules == null)
|
|
_rulesToCheck = instanceRules;
|
|
else
|
|
{
|
|
// both have values - consolidate into instance rules
|
|
_rulesToCheck = instanceRules;
|
|
foreach (KeyValuePair<string, RulesList> de in typeRules.RulesDictionary)
|
|
{
|
|
RulesList rules = _rulesToCheck.GetRulesForProperty(de.Key, true);
|
|
List<IRuleMethod> instanceList = rules.GetList(false);
|
|
instanceList.AddRange(de.Value.GetList(false));
|
|
List<string> dependancy = de.Value.GetDependancyList(false);
|
|
if (dependancy != null)
|
|
rules.GetDependancyList(true).AddRange(dependancy);
|
|
}
|
|
}
|
|
}
|
|
return _rulesToCheck;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns an array containing the text descriptions of all
|
|
/// validation rules associated with this object.
|
|
/// </summary>
|
|
/// <returns>String array.</returns>
|
|
/// <remarks></remarks>
|
|
public string[] GetRuleDescriptions()
|
|
{
|
|
List<string> result = new List<string>();
|
|
ValidationRulesManager rules = RulesToCheck;
|
|
if (rules != null)
|
|
{
|
|
foreach (KeyValuePair<string, RulesList> de in rules.RulesDictionary)
|
|
{
|
|
List<IRuleMethod> list = de.Value.GetList(false);
|
|
for (int i = 0; i < list.Count; i++)
|
|
{
|
|
IRuleMethod rule = list[i];
|
|
result.Add(rule.ToString());
|
|
}
|
|
}
|
|
}
|
|
return result.ToArray();
|
|
}
|
|
|
|
#region Short-Circuiting
|
|
|
|
/// <summary>
|
|
/// Gets or sets the priority through which
|
|
/// CheckRules should process before short-circuiting
|
|
/// processing on broken rules.
|
|
/// </summary>
|
|
/// <value>Defaults to 0.</value>
|
|
/// <remarks>
|
|
/// All rules for each property are processed by CheckRules
|
|
/// though this priority. Rules with lower priorities are
|
|
/// only processed if no previous rule has been marked as
|
|
/// broken.
|
|
/// </remarks>
|
|
public int ProcessThroughPriority
|
|
{
|
|
get { return _processThroughPriority; }
|
|
set { _processThroughPriority = value; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Adding Instance Rules
|
|
|
|
/// <summary>
|
|
/// Adds a rule to the list of rules to be enforced.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// A rule is implemented by a method which conforms to the
|
|
/// method signature defined by the RuleHandler delegate.
|
|
/// </para><para>
|
|
/// The propertyName may be used by the method that implements the rule
|
|
/// in order to retrieve the value to be validated. If the rule
|
|
/// implementation is inside the target object then it probably has
|
|
/// direct access to all data. However, if the rule implementation
|
|
/// is outside the target object then it will need to use reflection
|
|
/// or CallByName to dynamically invoke this property to retrieve
|
|
/// the value to be validated.
|
|
/// </para>
|
|
/// </remarks>
|
|
/// <param name="handler">The method that implements the rule.</param>
|
|
/// <param name="propertyName">
|
|
/// The property name on the target object where the rule implementation can retrieve
|
|
/// the value to be validated.
|
|
/// </param>
|
|
public void AddInstanceRule(RuleHandler handler, string propertyName)
|
|
{
|
|
GetInstanceRules(true).AddRule(handler, new RuleArgs(propertyName), 0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a rule to the list of rules to be enforced.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// A rule is implemented by a method which conforms to the
|
|
/// method signature defined by the RuleHandler delegate.
|
|
/// </para><para>
|
|
/// The propertyName may be used by the method that implements the rule
|
|
/// in order to retrieve the value to be validated. If the rule
|
|
/// implementation is inside the target object then it probably has
|
|
/// direct access to all data. However, if the rule implementation
|
|
/// is outside the target object then it will need to use reflection
|
|
/// or CallByName to dynamically invoke this property to retrieve
|
|
/// the value to be validated.
|
|
/// </para>
|
|
/// </remarks>
|
|
/// <param name="handler">The method that implements the rule.</param>
|
|
/// <param name="propertyName">
|
|
/// The property name on the target object where the rule implementation can retrieve
|
|
/// the value to be validated.
|
|
/// </param>
|
|
/// <param name="priority">
|
|
/// The priority of the rule, where lower numbers are processed first.
|
|
/// </param>
|
|
public void AddInstanceRule(RuleHandler handler, string propertyName, int priority)
|
|
{
|
|
GetInstanceRules(true).AddRule(handler, new RuleArgs(propertyName), priority);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a rule to the list of rules to be enforced.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// A rule is implemented by a method which conforms to the
|
|
/// method signature defined by the RuleHandler delegate.
|
|
/// </para><para>
|
|
/// The propertyName may be used by the method that implements the rule
|
|
/// in order to retrieve the value to be validated. If the rule
|
|
/// implementation is inside the target object then it probably has
|
|
/// direct access to all data. However, if the rule implementation
|
|
/// is outside the target object then it will need to use reflection
|
|
/// or CallByName to dynamically invoke this property to retrieve
|
|
/// the value to be validated.
|
|
/// </para>
|
|
/// </remarks>
|
|
/// <param name="handler">The method that implements the rule.</param>
|
|
/// <param name="propertyName">
|
|
/// The property name on the target object where the rule implementation can retrieve
|
|
/// the value to be validated.
|
|
/// </param>
|
|
/// <typeparam name="T">Type of the business object to be validated.</typeparam>
|
|
public void AddInstanceRule<T>(RuleHandler<T, RuleArgs> handler, string propertyName)
|
|
{
|
|
GetInstanceRules(true).AddRule<T, RuleArgs>(handler, new RuleArgs(propertyName), 0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a rule to the list of rules to be enforced.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// A rule is implemented by a method which conforms to the
|
|
/// method signature defined by the RuleHandler delegate.
|
|
/// </para><para>
|
|
/// The propertyName may be used by the method that implements the rule
|
|
/// in order to retrieve the value to be validated. If the rule
|
|
/// implementation is inside the target object then it probably has
|
|
/// direct access to all data. However, if the rule implementation
|
|
/// is outside the target object then it will need to use reflection
|
|
/// or CallByName to dynamically invoke this property to retrieve
|
|
/// the value to be validated.
|
|
/// </para>
|
|
/// </remarks>
|
|
/// <param name="handler">The method that implements the rule.</param>
|
|
/// <param name="propertyName">
|
|
/// The property name on the target object where the rule implementation can retrieve
|
|
/// the value to be validated.
|
|
/// </param>
|
|
/// <param name="priority">
|
|
/// The priority of the rule, where lower numbers are processed first.
|
|
/// </param>
|
|
/// <typeparam name="T">Type of the business object to be validated.</typeparam>
|
|
public void AddInstanceRule<T>(RuleHandler<T, RuleArgs> handler, string propertyName, int priority)
|
|
{
|
|
GetInstanceRules(true).AddRule<T, RuleArgs>(handler, new RuleArgs(propertyName), priority);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a rule to the list of rules to be enforced.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// A rule is implemented by a method which conforms to the
|
|
/// method signature defined by the RuleHandler delegate.
|
|
/// </remarks>
|
|
/// <param name="handler">The method that implements the rule.</param>
|
|
/// <param name="args">
|
|
/// A RuleArgs object specifying the property name and other arguments
|
|
/// passed to the rule method
|
|
/// </param>
|
|
public void AddInstanceRule(RuleHandler handler, RuleArgs args)
|
|
{
|
|
GetInstanceRules(true).AddRule(handler, args, 0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a rule to the list of rules to be enforced.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// A rule is implemented by a method which conforms to the
|
|
/// method signature defined by the RuleHandler delegate.
|
|
/// </remarks>
|
|
/// <param name="handler">The method that implements the rule.</param>
|
|
/// <param name="args">
|
|
/// A RuleArgs object specifying the property name and other arguments
|
|
/// passed to the rule method
|
|
/// </param>
|
|
/// <param name="priority">
|
|
/// The priority of the rule, where lower numbers are processed first.
|
|
/// </param>
|
|
public void AddInstanceRule(RuleHandler handler, RuleArgs args, int priority)
|
|
{
|
|
GetInstanceRules(true).AddRule(handler, args, priority);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a rule to the list of rules to be enforced.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// A rule is implemented by a method which conforms to the
|
|
/// method signature defined by the RuleHandler delegate.
|
|
/// </remarks>
|
|
/// <typeparam name="T">Type of the target object.</typeparam>
|
|
/// <typeparam name="R">Type of the arguments parameter.</typeparam>
|
|
/// <param name="handler">The method that implements the rule.</param>
|
|
/// <param name="args">
|
|
/// A RuleArgs object specifying the property name and other arguments
|
|
/// passed to the rule method
|
|
/// </param>
|
|
public void AddInstanceRule<T, R>(RuleHandler<T, R> handler, R args) where R : RuleArgs
|
|
{
|
|
GetInstanceRules(true).AddRule(handler, args, 0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a rule to the list of rules to be enforced.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// A rule is implemented by a method which conforms to the
|
|
/// method signature defined by the RuleHandler delegate.
|
|
/// </remarks>
|
|
/// <typeparam name="T">Type of the target object.</typeparam>
|
|
/// <typeparam name="R">Type of the arguments parameter.</typeparam>
|
|
/// <param name="handler">The method that implements the rule.</param>
|
|
/// <param name="args">
|
|
/// A RuleArgs object specifying the property name and other arguments
|
|
/// passed to the rule method
|
|
/// </param>
|
|
/// <param name="priority">
|
|
/// The priority of the rule, where lower numbers are processed first.
|
|
/// </param>
|
|
public void AddInstanceRule<T, R>(RuleHandler<T, R> handler, R args, int priority) where R : RuleArgs
|
|
{
|
|
GetInstanceRules(true).AddRule(handler, args, priority);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Adding Per-Type Rules
|
|
|
|
/// <summary>
|
|
/// Adds a rule to the list of rules to be enforced.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// A rule is implemented by a method which conforms to the
|
|
/// method signature defined by the RuleHandler delegate.
|
|
/// </para><para>
|
|
/// The propertyName may be used by the method that implements the rule
|
|
/// in order to retrieve the value to be validated. If the rule
|
|
/// implementation is inside the target object then it probably has
|
|
/// direct access to all data. However, if the rule implementation
|
|
/// is outside the target object then it will need to use reflection
|
|
/// or CallByName to dynamically invoke this property to retrieve
|
|
/// the value to be validated.
|
|
/// </para>
|
|
/// </remarks>
|
|
/// <param name="handler">The method that implements the rule.</param>
|
|
/// <param name="propertyName">
|
|
/// The property name on the target object where the rule implementation can retrieve
|
|
/// the value to be validated.
|
|
/// </param>
|
|
public void AddRule(RuleHandler handler, string propertyName)
|
|
{
|
|
ValidateHandler(handler);
|
|
GetTypeRules(true).AddRule(handler, new RuleArgs(propertyName), 0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a rule to the list of rules to be enforced.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// A rule is implemented by a method which conforms to the
|
|
/// method signature defined by the RuleHandler delegate.
|
|
/// </para><para>
|
|
/// The propertyName may be used by the method that implements the rule
|
|
/// in order to retrieve the value to be validated. If the rule
|
|
/// implementation is inside the target object then it probably has
|
|
/// direct access to all data. However, if the rule implementation
|
|
/// is outside the target object then it will need to use reflection
|
|
/// or CallByName to dynamically invoke this property to retrieve
|
|
/// the value to be validated.
|
|
/// </para>
|
|
/// </remarks>
|
|
/// <param name="handler">The method that implements the rule.</param>
|
|
/// <param name="propertyName">
|
|
/// The property name on the target object where the rule implementation can retrieve
|
|
/// the value to be validated.
|
|
/// </param>
|
|
/// <param name="priority">
|
|
/// The priority of the rule, where lower numbers are processed first.
|
|
/// </param>
|
|
public void AddRule(RuleHandler handler, string propertyName, int priority)
|
|
{
|
|
ValidateHandler(handler);
|
|
GetTypeRules(true).AddRule(handler, new RuleArgs(propertyName), priority);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a rule to the list of rules to be enforced.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// A rule is implemented by a method which conforms to the
|
|
/// method signature defined by the RuleHandler delegate.
|
|
/// </para><para>
|
|
/// The propertyName may be used by the method that implements the rule
|
|
/// in order to retrieve the value to be validated. If the rule
|
|
/// implementation is inside the target object then it probably has
|
|
/// direct access to all data. However, if the rule implementation
|
|
/// is outside the target object then it will need to use reflection
|
|
/// or CallByName to dynamically invoke this property to retrieve
|
|
/// the value to be validated.
|
|
/// </para>
|
|
/// </remarks>
|
|
/// <param name="handler">The method that implements the rule.</param>
|
|
/// <param name="propertyName">
|
|
/// The property name on the target object where the rule implementation can retrieve
|
|
/// the value to be validated.
|
|
/// </param>
|
|
public void AddRule<T>(RuleHandler<T, RuleArgs> handler, string propertyName)
|
|
{
|
|
ValidateHandler(handler);
|
|
GetTypeRules(true).AddRule<T, RuleArgs>(handler, new RuleArgs(propertyName), 0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a rule to the list of rules to be enforced.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// A rule is implemented by a method which conforms to the
|
|
/// method signature defined by the RuleHandler delegate.
|
|
/// </para><para>
|
|
/// The propertyName may be used by the method that implements the rule
|
|
/// in order to retrieve the value to be validated. If the rule
|
|
/// implementation is inside the target object then it probably has
|
|
/// direct access to all data. However, if the rule implementation
|
|
/// is outside the target object then it will need to use reflection
|
|
/// or CallByName to dynamically invoke this property to retrieve
|
|
/// the value to be validated.
|
|
/// </para>
|
|
/// </remarks>
|
|
/// <param name="handler">The method that implements the rule.</param>
|
|
/// <param name="propertyName">
|
|
/// The property name on the target object where the rule implementation can retrieve
|
|
/// the value to be validated.
|
|
/// </param>
|
|
/// <param name="priority">
|
|
/// The priority of the rule, where lower numbers are processed first.
|
|
/// </param>
|
|
public void AddRule<T>(RuleHandler<T, RuleArgs> handler, string propertyName, int priority)
|
|
{
|
|
ValidateHandler(handler);
|
|
GetTypeRules(true).AddRule<T, RuleArgs>(handler, new RuleArgs(propertyName), priority);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a rule to the list of rules to be enforced.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// A rule is implemented by a method which conforms to the
|
|
/// method signature defined by the RuleHandler delegate.
|
|
/// </remarks>
|
|
/// <param name="handler">The method that implements the rule.</param>
|
|
/// <param name="args">
|
|
/// A RuleArgs object specifying the property name and other arguments
|
|
/// passed to the rule method
|
|
/// </param>
|
|
public void AddRule(RuleHandler handler, RuleArgs args)
|
|
{
|
|
ValidateHandler(handler);
|
|
GetTypeRules(true).AddRule(handler, args, 0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a rule to the list of rules to be enforced.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// A rule is implemented by a method which conforms to the
|
|
/// method signature defined by the RuleHandler delegate.
|
|
/// </remarks>
|
|
/// <param name="handler">The method that implements the rule.</param>
|
|
/// <param name="args">
|
|
/// A RuleArgs object specifying the property name and other arguments
|
|
/// passed to the rule method
|
|
/// </param>
|
|
/// <param name="priority">
|
|
/// The priority of the rule, where lower numbers are processed first.
|
|
/// </param>
|
|
public void AddRule(RuleHandler handler, RuleArgs args, int priority)
|
|
{
|
|
ValidateHandler(handler);
|
|
GetTypeRules(true).AddRule(handler, args, priority);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a rule to the list of rules to be enforced.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// A rule is implemented by a method which conforms to the
|
|
/// method signature defined by the RuleHandler delegate.
|
|
/// </remarks>
|
|
/// <typeparam name="T">Type of the target object.</typeparam>
|
|
/// <typeparam name="R">Type of the arguments parameter.</typeparam>
|
|
/// <param name="handler">The method that implements the rule.</param>
|
|
/// <param name="args">
|
|
/// A RuleArgs object specifying the property name and other arguments
|
|
/// passed to the rule method
|
|
/// </param>
|
|
public void AddRule<T, R>(RuleHandler<T, R> handler, R args) where R : RuleArgs
|
|
{
|
|
ValidateHandler(handler);
|
|
GetTypeRules(true).AddRule(handler, args, 0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a rule to the list of rules to be enforced.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// A rule is implemented by a method which conforms to the
|
|
/// method signature defined by the RuleHandler delegate.
|
|
/// </remarks>
|
|
/// <typeparam name="T">Type of the target object.</typeparam>
|
|
/// <typeparam name="R">Type of the arguments parameter.</typeparam>
|
|
/// <param name="handler">The method that implements the rule.</param>
|
|
/// <param name="args">
|
|
/// A RuleArgs object specifying the property name and other arguments
|
|
/// passed to the rule method
|
|
/// </param>
|
|
/// <param name="priority">
|
|
/// The priority of the rule, where lower numbers are processed first.
|
|
/// </param>
|
|
public void AddRule<T, R>(RuleHandler<T, R> handler, R args, int priority) where R : RuleArgs
|
|
{
|
|
ValidateHandler(handler);
|
|
GetTypeRules(true).AddRule(handler, args, priority);
|
|
}
|
|
|
|
private bool ValidateHandler(RuleHandler handler)
|
|
{
|
|
return ValidateHandler(handler.Method);
|
|
}
|
|
|
|
private bool ValidateHandler<T, R>(RuleHandler<T, R> handler) where R : RuleArgs
|
|
{
|
|
return ValidateHandler(handler.Method);
|
|
}
|
|
|
|
private bool ValidateHandler(System.Reflection.MethodInfo method)
|
|
{
|
|
if (!method.IsStatic && method.DeclaringType.Equals(_target.GetType()))
|
|
throw new InvalidOperationException(
|
|
string.Format("{0}: {1}",
|
|
Properties.Resources.InvalidRuleMethodException, method.Name));
|
|
return true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Adding per-type dependancies
|
|
|
|
/// <summary>
|
|
/// Adds a property to the list of dependencies for
|
|
/// the specified property
|
|
/// </summary>
|
|
/// <param name="propertyName">
|
|
/// The name of the property.
|
|
/// </param>
|
|
/// <param name="dependantPropertyName">
|
|
/// The name of the depandent property.
|
|
/// </param>
|
|
/// <remarks>
|
|
/// When rules are checked for propertyName, they will
|
|
/// also be checked for any dependant properties associated
|
|
/// with that property.
|
|
/// </remarks>
|
|
public void AddDependantProperty(string propertyName, string dependantPropertyName)
|
|
{
|
|
GetTypeRules(true).AddDependantProperty(propertyName, dependantPropertyName);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a property to the list of dependencies for
|
|
/// the specified property
|
|
/// </summary>
|
|
/// <param name="propertyName">
|
|
/// The name of the property.
|
|
/// </param>
|
|
/// <param name="dependantPropertyName">
|
|
/// The name of the depandent property.
|
|
/// </param>
|
|
/// <param name="isBidirectional">
|
|
/// If <see langword="true"/> then a
|
|
/// reverse dependancy is also established
|
|
/// from dependantPropertyName to propertyName.
|
|
/// </param>
|
|
/// <remarks>
|
|
/// When rules are checked for propertyName, they will
|
|
/// also be checked for any dependant properties associated
|
|
/// with that property. If isBidirectional is
|
|
/// <see langword="true"/> then an additional association
|
|
/// is set up so when rules are checked for
|
|
/// dependantPropertyName the rules for propertyName
|
|
/// will also be checked.
|
|
/// </remarks>
|
|
public void AddDependantProperty(string propertyName, string dependantPropertyName, bool isBidirectional)
|
|
{
|
|
|
|
ValidationRulesManager mgr = GetTypeRules(true);
|
|
mgr.AddDependantProperty(propertyName, dependantPropertyName);
|
|
if (isBidirectional)
|
|
{
|
|
mgr.AddDependantProperty(dependantPropertyName, propertyName);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Checking Rules
|
|
|
|
/// <summary>
|
|
/// Invokes all rule methods associated with
|
|
/// the specified property and any
|
|
/// dependant properties.
|
|
/// </summary>
|
|
/// <param name="propertyName">The name of the property to validate.</param>
|
|
public void CheckRules(string propertyName)
|
|
{
|
|
// get the rules dictionary
|
|
ValidationRulesManager rules = RulesToCheck;
|
|
if (rules != null)
|
|
{
|
|
// get the rules list for this property
|
|
RulesList rulesList = rules.GetRulesForProperty(propertyName, false);
|
|
if (rulesList != null)
|
|
{
|
|
// get the actual list of rules (sorted by priority)
|
|
List<IRuleMethod> list = rulesList.GetList(true);
|
|
if (list != null)
|
|
CheckRules(list);
|
|
List<string> dependancies = rulesList.GetDependancyList(false);
|
|
if (dependancies != null)
|
|
{
|
|
for (int i = 0; i < dependancies.Count; i++)
|
|
{
|
|
string dependantProperty = dependancies[i];
|
|
CheckRules(rules, dependantProperty);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CheckRules(ValidationRulesManager rules, string propertyName)
|
|
{
|
|
// get the rules list for this property
|
|
RulesList rulesList = rules.GetRulesForProperty(propertyName, false);
|
|
if (rulesList != null)
|
|
{
|
|
// get the actual list of rules (sorted by priority)
|
|
List<IRuleMethod> list = rulesList.GetList(true);
|
|
if (list != null)
|
|
CheckRules(list);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invokes all rule methods for all properties
|
|
/// in the object.
|
|
/// </summary>
|
|
public void CheckRules()
|
|
{
|
|
ValidationRulesManager rules = RulesToCheck;
|
|
if (rules != null)
|
|
{
|
|
foreach (KeyValuePair<string, RulesList> de in rules.RulesDictionary)
|
|
CheckRules(de.Value.GetList(true));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Given a list
|
|
/// containing IRuleMethod objects, this
|
|
/// method executes all those rule methods.
|
|
/// </summary>
|
|
private void CheckRules(List<IRuleMethod> list)
|
|
{
|
|
bool previousRuleBroken = false;
|
|
bool shortCircuited = false;
|
|
|
|
for (int index = 0; index < list.Count; index++)
|
|
{
|
|
IRuleMethod rule = list[index];
|
|
// see if short-circuiting should kick in
|
|
if (!shortCircuited && (previousRuleBroken && rule.Priority > _processThroughPriority))
|
|
shortCircuited = true;
|
|
|
|
if (shortCircuited)
|
|
{
|
|
// we're short-circuited, so just remove
|
|
// all remaining broken rule entries
|
|
BrokenRulesList.Remove(rule);
|
|
}
|
|
else
|
|
{
|
|
// we're not short-circuited, so check rule
|
|
if (rule.Invoke(_target))
|
|
{
|
|
// the rule is not broken
|
|
BrokenRulesList.Remove(rule);
|
|
}
|
|
else
|
|
{
|
|
// the rule is broken
|
|
BrokenRulesList.Add(rule);
|
|
if (rule.RuleArgs.Severity == RuleSeverity.Error)
|
|
previousRuleBroken = true;
|
|
}
|
|
if (rule.RuleArgs.StopProcessing)
|
|
shortCircuited = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Status Retrieval
|
|
|
|
/// <summary>
|
|
/// Returns a value indicating whether there are any broken rules
|
|
/// at this time.
|
|
/// </summary>
|
|
/// <returns>A value indicating whether any rules are broken.</returns>
|
|
internal bool IsValid
|
|
{
|
|
get { return BrokenRulesList.ErrorCount == 0; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns a reference to the readonly collection of broken
|
|
/// business rules.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The reference returned points to the actual collection object.
|
|
/// This means that as rules are marked broken or unbroken over time,
|
|
/// the underlying data will change. Because of this, the UI developer
|
|
/// can bind a display directly to this collection to get a dynamic
|
|
/// display of the broken rules at all times.
|
|
/// </remarks>
|
|
/// <returns>A reference to the collection of broken rules.</returns>
|
|
public BrokenRulesCollection GetBrokenRules()
|
|
{
|
|
return BrokenRulesList;
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
} |