📄 brokenrules.cs
字号:
using System;
using System.Collections;
using System.Collections.Specialized;
using CSLA.Resources;
namespace CSLA
{
/// <summary>
/// Tracks the business rules broken within a business object.
/// </summary>
[Serializable()]
public class BrokenRules
{
#region Rule structure
/// <summary>
/// Stores details about a specific broken business rule.
/// </summary>
[Serializable()]
public struct Rule
{
string _name;
string _description;
string _property;
internal Rule(string name, string description)
{
_name = name;
_description = description;
_property = string.Empty;
}
internal Rule(string name, string description, string property)
{
_name = name;
_description = description;
_property = property;
}
/// <summary>
/// Provides access to the name of the broken rule.
/// </summary>
/// <remarks>
/// This value is actually readonly, not readwrite. Any new
/// value set into this property is ignored. The property is only
/// readwrite because that is required to support data binding
/// within Web Forms.
/// </remarks>
/// <value>The name of the rule.</value>
public string Name
{
get
{
return _name;
}
set
{
// the property must be read-write for Web Forms data binding
// to work, but we really don't want to allow the value to be
// changed dynamically so we ignore any attempt to set it
}
}
/// <summary>
/// Provides access to the description of the broken rule.
/// </summary>
/// <remarks>
/// This value is actually readonly, not readwrite. Any new
/// value set into this property is ignored. The property is only
/// readwrite because that is required to support data binding
/// within Web Forms.
/// </remarks>
/// <value>The description of the rule.</value>
public string Description
{
get
{
return _description;
}
set
{
// the property must be read-write for Web Forms data binding
// to work, but we really don't want to allow the value to be
// changed dynamically so we ignore any attempt to set it
}
}
/// <summary>
/// Provides access to the property affected by the broken rule.
/// </summary>
/// <remarks>
/// This value is actually readonly, not readwrite. Any new
/// value set into this property is ignored. The property is only
/// readwrite because that is required to support data binding
/// within Web Forms.
/// </remarks>
/// <value>The property affected by the rule.</value>
public string Property
{
get
{
return _property;
}
set
{
// the property must be read-write for Web Forms data binding
// to work, but we really don't want to allow the value to be
// changed dynamically so we ignore any attempt to set it
}
}
}
#endregion
#region RulesCollection
/// <summary>
/// A collection of currently broken rules.
/// </summary>
/// <remarks>
/// This collection is readonly and can be safely made available
/// to code outside the business object such as the UI. This allows
/// external code, such as a UI, to display the list of broken rules
/// to the user.
/// </remarks>
[Serializable()]
public class RulesCollection : CSLA.Core.BindableCollectionBase
{
bool _validToEdit = false;
/// <summary>
/// Returns a <see cref="T:CSLA.BrokenRules.Rule" /> object
/// containing details about a specific broken business rule.
/// </summary>
/// <param name="Index"></param>
/// <returns></returns>
public Rule this [int index]
{
get
{
return (Rule)List[index];
}
}
/// <summary>
/// Returns the first <see cref="T:CSLA.BrokenRules.Rule" /> object
/// corresponding to the specified property.
/// </summary>
/// <remarks>
/// <para>
/// When a rule is marked as broken, the business developer can provide
/// an optional Property parameter. This parameter is the name of the
/// Property on the object that is most affected by the rule. Data binding
/// may later use the IDataErrorInfo interface to query the object for
/// details about errors corresponding to specific properties, and this
/// value will be returned as a result of that query.
/// </para><para>
/// Code in a business object or UI can also use this value to retrieve
/// the first broken rule in <see cref="T:CSLA.BrokenRules" /> that corresponds
/// to a specfic Property on the object.
/// </para>
/// </remarks>
/// <param name="Property">The name of the property affected by the rule.</param>
public Rule RuleForProperty(string property)
{
foreach(Rule item in List)
if(item.Property == property)
return item;
return new Rule();
}
internal RulesCollection()
{
AllowEdit = false;
AllowRemove = false;
AllowNew = false;
}
internal void Add(string name, string description)
{
Remove(name);
_validToEdit = true;
List.Add(new Rule(name, description));
_validToEdit = false;
}
internal void Add(string name, string description, string property)
{
Remove(name);
_validToEdit = true;
List.Add(new Rule(name, description, property));
_validToEdit = false;
}
internal void Remove(string name)
{
// we loop through using a numeric counter because
// the base class Remove requires a numeric index
_validToEdit = true;
for(int index = 0; index < List.Count; index++)
if(((Rule)List[index]).Name == name)
{
List.Remove(List[index]);
break;
}
_validToEdit = false;
}
internal bool Contains(string name)
{
for(int index = 0; index < List.Count; index++)
if(((Rule)List[index]).Name == name)
return true;
return false;
}
protected override void OnClear()
{
if(!_validToEdit)
throw new NotSupportedException(Strings.GetResourceString("ClearInvalidException"));
}
protected override void OnInsert(int index, object val)
{
if(!_validToEdit)
throw new NotSupportedException(Strings.GetResourceString("InsertInvalidException"));
}
protected override void OnRemove(int index, object val)
{
if(!_validToEdit)
throw new NotSupportedException(Strings.GetResourceString("RemoveInvalidException"));
}
protected override void OnSet(int index, object oldValue, object newValue)
{
if(!_validToEdit)
throw new NotSupportedException(
Strings.GetResourceString("ChangeInvalidException"));
}
}
#endregion
private RulesCollection _brokenRules = new RulesCollection();
[NonSerialized()]
[NotUndoable()]
private object _target;
#region Rule Manager
/// <summary>
/// Sets the target object so the Rules Manager functionality
/// has a reference to the object containing the data to
/// be validated.
/// </summary>
/// <remarks>
/// The object here is typically your business object. In your
/// business class you'll implement a method to set up your
/// business rules. As you do so, you need to call this method
/// to give BrokenRules a reference to your business object
/// so it has access to your object's data.
/// </remarks>
/// <param name="target">A reference to the object containing
/// the data to be validated.</param>
public void SetTargetObject(object target)
{
_target = target;
}
#region RuleHandler delegate
/// <summary>
/// Delegate that defines the method signature for all rule handler methods.
/// </summary>
/// <remarks>
/// <para>
/// When implementing a rule handler, you must conform to the method signature
/// defined by this delegate. You should also apply the Description attribute
/// to your method to provide a meaningful description for your rule.
/// </para><para>
/// The method implementing the rule must return True if the data is valid and
/// return False if the data is invalid.
/// </para>
/// </remarks>
public delegate bool RuleHandler(object target, RuleArgs e);
#endregion
#region RuleArgs class
/// <summary>
/// Object providing extra information to methods that
/// implement business rules.
/// </summary>
public class RuleArgs
{
private string _propertyName;
private string _description;
/// <summary>
/// The (optional) name of the property to be validated.
/// </summary>
public string PropertyName
{
get
{
return _propertyName;
}
}
/// <summary>
/// Set by the rule handler method to describe the broken
/// rule.
/// </summary>
/// <remarks>
/// <para>
/// If the rule handler sets this property, this value will override
/// any description attribute value associated with the rule handler
/// method.
/// </para><para>
/// The description string returned via this property
/// is provided to the UI or other consumer
/// about which rules are broken. These descriptions are intended
/// for end-user display.
/// </para><para>
/// The description value is a .NET format string, and it can include
/// the following tokens in addition to literal text:
/// </para><para>
/// {0} - the RuleName value
/// </para><para>
/// {1} - the PropertyName value
/// </para><para>
/// {2} - the full type name of the target object
/// </para><para>
/// {3} - the ToString value of the target object
/// </para><para>
/// You can use these tokens in your description string and the
/// appropriate values will be substituted for the tokens at
/// runtime.
/// </para>
/// </remarks>
public string Description
{
get
{
return _description;
}
set
{
_description = value;
}
}
/// <summary>
/// Creates an instance of RuleArgs.
/// </summary>
public RuleArgs()
{
}
/// <summary>
/// Creates an instance of RuleArgs.
/// </summary>
/// <param name="propertyName">The name of the property to be validated.</param>
public RuleArgs(string propertyName)
{
_propertyName = propertyName;
}
#region Empty
private static RuleArgs _emptyArgs = new RuleArgs();
/// <summary>
/// Returns an empty RuleArgs object.
/// </summary>
public static RuleArgs Empty
{
get
{
return _emptyArgs;
}
}
#endregion
}
#endregion
#region Description attribute
/// <summary>
/// Defines the description of a business rule.
/// </summary>
/// <remarks>
/// <para>
/// The description in this attribute is used by BusinessRules
/// as information that is provided to the UI or other consumer
/// about which rules are broken. These descriptions are intended
/// for end-user display.
/// </para><para>
/// The description value is a .NET format string, and it can include
/// the following tokens in addition to literal text:
/// </para><para>
/// {0} - the RuleName value
/// </para><para>
/// {1} - the PropertyName value
/// </para><para>
/// {2} - the full type name of the target object
/// </para><para>
/// {3} - the ToString value of the target object
/// </para><para>
/// You can use these tokens in your description string and the
/// appropriate values will be substituted for the tokens at
/// runtime.
/// </para><para>
/// Instead of using this attribute, a rule handler method can
/// set the Description property of the RuleArgs parameter to
/// a description string. That approach can provide a more dynamic
/// way to generate descriptions of broken rules.
/// </para>
/// </remarks>
[AttributeUsage(AttributeTargets.Method)]
public class DescriptionAttribute : Attribute
{
private string _text = string.Empty;
/// <summary>
/// Initializes the attribute with a description.
/// </summary>
public DescriptionAttribute(string description)
{
_text = description;
}
/// <summary>
/// Returns the description value of the attribute.
/// </summary>
public override string ToString()
{
return _text;
}
}
#endregion
#region RuleMethod Class
/// <summary>
/// Tracks all information for a rule.
/// </summary>
private class RuleMethod
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -