📄 brokenrules.cs
字号:
private RuleHandler _handler;
private object _target;
private string _ruleName;
private RuleArgs _args;
private string _description;
/// <summary>
/// Returns the name of the method implementing the rule
/// and the property, field or column name to which the
/// rule applies.
/// </summary>
public override string ToString()
{
if(RuleArgs.PropertyName == null)
return _handler.Method.Name;
else
return _handler.Method.Name + "!" + RuleArgs.PropertyName;
}
/// <summary>
/// Returns the delegate to the method implementing the rule.
/// </summary>
public RuleHandler Handler
{
get
{
return _handler;
}
}
/// <summary>
/// Returns the user-friendly name of the rule.
/// </summary>
public string RuleName
{
get
{
return _ruleName;
}
}
/// <summary>
/// Returns the name of the field, property or column
/// to which the rule applies.
/// </summary>
public RuleArgs RuleArgs
{
get
{
return _args;
}
}
/// <summary>
/// Returns the formatted description of the rule.
/// </summary>
public string Description
{
get
{
if(_args.Description != null && _args.Description.Length > 0)
return string.Format(_args.Description, RuleName, RuleArgs.PropertyName,
TypeName(_target), _target.ToString());
else
return string.Format(_description, RuleName, RuleArgs.PropertyName, TypeName(_target), _target.ToString());
}
}
private string TypeName(object obj)
{
return obj.GetType().Name;
}
/// <summary>
/// Retrieves the description text from the Description
/// attribute on a RuleHandler method.
/// </summary>
private string GetDescription(RuleHandler handler)
{
object [] attrib = handler.Method.GetCustomAttributes(typeof(DescriptionAttribute), false);
if(attrib.Length > 0)
return attrib[0].ToString();
else
return "{2}.{0}:<no description>";
}
/// <summary>
/// Creates and initializes the rule.
/// </summary>
/// <param name="target">Reference to the object containing the data to validate.</param>
/// <param name="handler">The address of the method implementing the rule.</param>
/// <param name="ruleName">The user-friendly name of the rule.</param>
/// <param name="ruleArgs">A RuleArgs object containing data related to the rule.</param>
public RuleMethod(object target, RuleHandler handler, string ruleName, RuleArgs ruleArgs)
{
_target = target;
_handler = handler;
_description = GetDescription(handler);
_ruleName = ruleName;
_args = ruleArgs;
}
/// <summary>
/// Creates and initializes the rule.
/// </summary>
/// <param name="target">Reference to the object containing the data to validate.</param>
/// <param name="handler">The address of the method implementing the rule.</param>
/// <param name="ruleName">The user-friendly name of the rule.</param>
/// <param name="propertyName">The field, property or column to which the rule applies.</param>
public RuleMethod(object target, RuleHandler handler, string ruleName, string propertyName)
{
_target = target;
_handler = handler;
_description = GetDescription(handler);
_ruleName = ruleName;
_args = new RuleArgs(propertyName);
}
/// <summary>
/// Invokes the rule to validate the data.
/// </summary>
/// <returns>True if the data is valid, False if the data is invalid.</returns>
public bool Invoke()
{
return _handler(_target, _args);
}
}
#endregion
#region RulesList property
[NonSerialized()]
[NotUndoable()]
private HybridDictionary _rulesList;
private HybridDictionary RulesList
{
get
{
if(_rulesList == null)
_rulesList = new HybridDictionary();
return _rulesList;
}
}
#endregion
#region Adding Rules
/// Returns the ArrayList containing rules for a rule name. If
/// no ArrayList exists one is created and returned.
/// </summary>
private ArrayList GetRulesForName(string ruleName)
{
// get the ArrayList (if any) from the Hashtable
ArrayList list = (ArrayList)RulesList[ruleName];
if(list == null)
{
// there is no list for this name - create one
list = new ArrayList();
RulesList.Add(ruleName, list);
}
return list;
}
/// <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 ruleName is used to group all the rules that apply
/// to a specific field, property or concept. All rules applying
/// to the field or property should have the same rule name. When
/// rules are checked, they can be checked globally or for a
/// specific ruleName.
/// </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="ruleName">
/// A user-friendly identifier for the field/property
/// to which the rule applies.
/// </param>
public void AddRule(RuleHandler handler, string ruleName)
{
// get the ArrayList (if any) from the Hashtable
ArrayList list = GetRulesForName(ruleName);
// we have the list, add our new rule
list.Add(new RuleMethod(_target, handler, ruleName, RuleArgs.Empty));
}
/// <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 ruleName is used to group all the rules that apply
/// to a specific field, property or concept. All rules applying
/// to the field or property should have the same rule name. When
/// rules are checked, they can be checked globally or for a
/// specific ruleName.
/// </para>
/// </remarks>
/// <param name="handler">The method that implements the rule.</param>
/// <param name="ruleName">
/// A user-friendly identifier for the field/property
/// to which the rule applies.
/// </param>
/// <param name="ruleArgs">A RuleArgs object containing data
/// to be passed to the method implementing the rule.</param>
public void AddRule(RuleHandler handler, string ruleName, RuleArgs ruleArgs)
{
// get the ArrayList (if any) from the Hashtable
ArrayList list = GetRulesForName(ruleName);
// we have the list, add our new rule
list.Add(new RuleMethod(_target, handler, ruleName, ruleArgs));
}
/// <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 ruleName is used to group all the rules that apply
/// to a specific field, property or concept. All rules applying
/// to the field or property should have the same rule name. When
/// rules are checked, they can be checked globally or for a
/// specific ruleName.
/// </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="ruleName">
/// A user-friendly identifier for the field/property
/// to which the rule applies.
/// </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 ruleName, string propertyName)
{
// get the ArrayList (if any) from the Hashtable
ArrayList list = GetRulesForName(ruleName);
// we have the list, add our new rule
list.Add(new RuleMethod(_target, handler, ruleName, propertyName));
}
#endregion
#region Checking Rules
/// <summary>
/// Checks all the rules for a specific ruleName.
/// </summary>
/// <param name="ruleName">The ruleName to be validated.</param>
public void CheckRules(string ruleName)
{
// get the list of rules to check
ArrayList list = (ArrayList)RulesList[ruleName];
if(list == null) return;
// now check the rules
foreach(RuleMethod rule in list)
if(rule.Invoke())
UnBreakRule(rule);
else
BreakRule(rule);
}
/// <summary>
/// Checks all the rules for a target object.
/// </summary>
public void CheckRules()
{
// get the rules for each rule name
foreach(DictionaryEntry de in RulesList)
{
ArrayList list = (ArrayList)de.Value;
// now check the rules
foreach(RuleMethod rule in list)
if(rule.Invoke())
UnBreakRule(rule);
else
BreakRule(rule);
}
}
private void UnBreakRule(RuleMethod rule)
{
if(rule.RuleArgs.PropertyName == null)
Assert(rule.ToString(), string.Empty, false);
else
Assert(rule.ToString(), string.Empty, rule.RuleArgs.PropertyName, false);
}
private void BreakRule(RuleMethod rule)
{
if(rule.RuleArgs.PropertyName == null)
Assert(rule.ToString(), rule.Description, true);
else
Assert(rule.ToString(), rule.Description, rule.RuleArgs.PropertyName, true);
}
#endregion
#endregion // Rule Manager
#region Assert methods
RulesCollection _rules = new RulesCollection();
/// <summary>
/// This method is called by business logic within a business class to
/// indicate whether a business rule is broken.
/// </summary>
/// <remarks>
/// Rules are identified by their names. The description field is merely a
/// comment that is used for display to the end user. When a rule is marked as
/// broken, it is recorded under the rule name value. To mark the rule as not
/// broken, the same rule name must be used.
/// </remarks>
/// <param name="Rule">The name of the business rule.</param>
/// <param name="Description">The description of the business rule.</param>
/// <param name="IsBroken">True if the value is broken, False if it is not broken.</param>
public void Assert(string name, string description, bool isBroken)
{
if(isBroken)
_rules.Add(name, description);
else
_rules.Remove(name);
}
/// <summary>
/// This method is called by business logic within a business class to
/// indicate whether a business rule is broken.
/// </summary>
/// <remarks>
/// Rules are identified by their names. The description field is merely a
/// comment that is used for display to the end user. When a rule is marked as
/// broken, it is recorded under the rule name value. To mark the rule as not
/// broken, the same rule name must be used.
/// </remarks>
/// <param name="Rule">The name of the business rule.</param>
/// <param name="Description">The description of the business rule.</param>
/// <param name="Property">The property affected by the business rule.</param>
/// <param name="IsBroken">True if the value is broken, False if it is not broken.</param>
public void Assert(string rule, string description, string property, bool isBroken)
{
if(isBroken)
_rules.Add(rule, description, property);
else
_rules.Remove(rule);
}
#endregion
#region Status retrieval
/// <summary>
/// Returns a value indicating whether there are any broken rules
/// at this time. If there are broken rules, the business object
/// is assumed to be invalid and False is returned. If there are no
/// broken business rules True is returned.
/// </summary>
/// <returns>A value indicating whether any rules are broken.</returns>
public bool IsValid
{
get
{
return (_rules.Count == 0);
}
}
/// <summary>
/// Returns a value indicating whether a particular business rule
/// is currently broken.
/// </summary>
/// <param name="Rule">The name of the rule to check.</param>
/// <returns>A value indicating whether the rule is currently broken.</returns>
public bool IsBroken(string name)
{
return _rules.Contains(name);
}
/// <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 RulesCollection BrokenRulesCollection
{
get
{
return _rules;
}
}
/// <summary>
/// Returns the text of all broken rule descriptions, each
/// separated by cr/lf.
/// </summary>
/// <returns>The text of all broken rule descriptions.</returns>
public override string ToString()
{
System.Text.StringBuilder obj = new System.Text.StringBuilder();
bool first = true;
foreach(Rule item in _rules)
{
if(first)
first = false;
else
obj.Append(Environment.NewLine);
obj.Append(item.Description);
}
return obj.ToString();
}
#endregion
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -