⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 brokenrules.cs

📁 C# 版本的一个三层商业架构
💻 CS
📖 第 1 页 / 共 2 页
字号:
      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 + -