规则引擎:用来验证字符串是否符合预配置的规则,可以通过配置文件动态定义不同的字符串验证条件
规则引擎主代码(RuleEngine.cs )
using System;
using System.Text.Regulars;
namespace Rule
{
/// <summary>
/// Rule Engine
/// </summary>
public class RuleEngine
{
/// <summary>
/// If you want the RuleEngine throw an exception when checking rule failed,
/// please set this value to true
/// </summary>
private static bool _throwException = false;
public static bool ThrowExceptionCodeDirectly
{
set
{
_throwException = value;
}
get
{
return _throwException;
}
}
/// <summary>
/// Check a group of rules by setId
/// </summary>
/// <param name="setId">the set id which you defined in configuration file</param>
/// <param name="value">the value you want check</param>
/// <returns>checking result</returns>
public static bool Process(string setId, string value)
{
bool result = false;
RuleSet ruleSet = ConfigCache.GetRuleSet(setId);
if (ruleSet!=null && ruleSet.RuleIdList!=null)
{
Rule rule;
for (int i = 0; i < ruleSet.RuleIdList.Length; i++)
{
rule = ConfigCache.GetRule(ruleSet.RuleIdList[i]);
if (!CheckRule(rule, value))
{
if (_throwException)
{
throw new Exception(rule.ErrorCode);
}
return false;
}
}
result = true;
}
return result;
}
private static bool CheckRule(Rule rule, string value)
{
bool result = false;
if (rule!=null)
{
switch (rule.Type)
{
case RuleType.IsNullOrEmpty:
result = !String.IsNullOrEmpty(value);
break;
case RuleType.MinLength:
if (!String.IsNullOrEmpty(value) && !String.IsNullOrEmpty(rule.Value))
{
int len = Int32.Parse(rule.Value);
result = (value.Length>=len);
}
break;
case RuleType.MaxLength:
if (!String.IsNullOrEmpty(value) && !String.IsNullOrEmpty(rule.Value))
{
int len = Int32.Parse(rule.Value);
result = (value.Length <= len);
}
break;
case RuleType.Pattern:
if (!String.IsNullOrEmpty(value) && !String.IsNullOrEmpty(rule.Value))
{
Regex reg = new Regex(rule.Value);
result = reg.IsMatch(value);
}
break;
case RuleType.HasSpace:
if (!String.IsNullOrEmpty(value))
{
result = !value.Contains(" ");
}
break;
default:
break;
}
}
return result;
}
}
/// <summary>
/// Rule Type Enumeration
/// Note: each int value should match with the rule type definition in config file
/// </summary>
public enum RuleType
{
IsNullOrEmpty = 1,
MinLength = 2,
MaxLength = 3,
Pattern = 4,
HasSpace = 5
}
/// <summary>
/// Rule Class
/// </summary>
public class Rule
{
/// <summary>
/// Rule ID
/// </summary>
private string _id;
public string ID
{
set
{
_id = value;
}
get
{
return _id;
}
}
/// <summary>
/// Rule Name
/// </summary>
private string _name;
public string Name
{
set
{
_name = value;
}
get
{
return _name;
}
}
/// <summary>
/// Rule Type
/// </summary>
private RuleType _type;
public RuleType Type
{
set
{
_type = value;
}
get
{
return _type;
}
}
/// <summary>
/// Set true to reverse a rule result
/// </summary>
private bool _isNot = false;
public bool IsNot
{
set
{
_isNot = value;
}
get
{
return _isNot;
}
}
/// <summary>
/// ErrorCode
/// </summary>
private string _errorCode;
public string ErrorCode
{
set
{
_errorCode = value;
}
get
{
return _errorCode;
}
}
/// <summary>
/// Value data of config file
/// </summary>
private string _value;
public string Value
{
set
{
_value = value;
}
get
{
return _value;
}
}
}
/// <summary>
/// A group of rules
/// </summary>
public class RuleSet
{
/// <summary>
/// Set Id
/// </summary>
private string _setId;
public string SetId
{
set
{
_setId = value;
}
get
{
return _setId;
}
}
/// <summary>
/// Rule Id List
/// </summary>
private string[] _ruleIdList;
public string[] RuleIdList
{
set
{
_ruleIdList = value;
}
get
{
return _ruleIdList;
}
}
}
}
using System.Text.Regulars;
namespace Rule
{
/// <summary>
/// Rule Engine
/// </summary>
public class RuleEngine
{
/// <summary>
/// If you want the RuleEngine throw an exception when checking rule failed,
/// please set this value to true
/// </summary>
private static bool _throwException = false;
public static bool ThrowExceptionCodeDirectly
{
set
{
_throwException = value;
}
get
{
return _throwException;
}
}
/// <summary>
/// Check a group of rules by setId
/// </summary>
/// <param name="setId">the set id which you defined in configuration file</param>
/// <param name="value">the value you want check</param>
/// <returns>checking result</returns>
public static bool Process(string setId, string value)
{
bool result = false;
RuleSet ruleSet = ConfigCache.GetRuleSet(setId);
if (ruleSet!=null && ruleSet.RuleIdList!=null)
{
Rule rule;
for (int i = 0; i < ruleSet.RuleIdList.Length; i++)
{
rule = ConfigCache.GetRule(ruleSet.RuleIdList[i]);
if (!CheckRule(rule, value))
{
if (_throwException)
{
throw new Exception(rule.ErrorCode);
}
return false;
}
}
result = true;
}
return result;
}
private static bool CheckRule(Rule rule, string value)
{
bool result = false;
if (rule!=null)
{
switch (rule.Type)
{
case RuleType.IsNullOrEmpty:
result = !String.IsNullOrEmpty(value);
break;
case RuleType.MinLength:
if (!String.IsNullOrEmpty(value) && !String.IsNullOrEmpty(rule.Value))
{
int len = Int32.Parse(rule.Value);
result = (value.Length>=len);
}
break;
case RuleType.MaxLength:
if (!String.IsNullOrEmpty(value) && !String.IsNullOrEmpty(rule.Value))
{
int len = Int32.Parse(rule.Value);
result = (value.Length <= len);
}
break;
case RuleType.Pattern:
if (!String.IsNullOrEmpty(value) && !String.IsNullOrEmpty(rule.Value))
{
Regex reg = new Regex(rule.Value);
result = reg.IsMatch(value);
}
break;
case RuleType.HasSpace:
if (!String.IsNullOrEmpty(value))
{
result = !value.Contains(" ");
}
break;
default:
break;
}
}
return result;
}
}
/// <summary>
/// Rule Type Enumeration
/// Note: each int value should match with the rule type definition in config file
/// </summary>
public enum RuleType
{
IsNullOrEmpty = 1,
MinLength = 2,
MaxLength = 3,
Pattern = 4,
HasSpace = 5
}
/// <summary>
/// Rule Class
/// </summary>
public class Rule
{
/// <summary>
/// Rule ID
/// </summary>
private string _id;
public string ID
{
set
{
_id = value;
}
get
{
return _id;
}
}
/// <summary>
/// Rule Name
/// </summary>
private string _name;
public string Name
{
set
{
_name = value;
}
get
{
return _name;
}
}
/// <summary>
/// Rule Type
/// </summary>
private RuleType _type;
public RuleType Type
{
set
{
_type = value;
}
get
{
return _type;
}
}
/// <summary>
/// Set true to reverse a rule result
/// </summary>
private bool _isNot = false;
public bool IsNot
{
set
{
_isNot = value;
}
get
{
return _isNot;
}
}
/// <summary>
/// ErrorCode
/// </summary>
private string _errorCode;
public string ErrorCode
{
set
{
_errorCode = value;
}
get
{
return _errorCode;
}
}
/// <summary>
/// Value data of config file
/// </summary>
private string _value;
public string Value
{
set
{
_value = value;
}
get
{
return _value;
}
}
}
/// <summary>
/// A group of rules
/// </summary>
public class RuleSet
{
/// <summary>
/// Set Id
/// </summary>
private string _setId;
public string SetId
{
set
{
_setId = value;
}
get
{
return _setId;
}
}
/// <summary>
/// Rule Id List
/// </summary>
private string[] _ruleIdList;
public string[] RuleIdList
{
set
{
_ruleIdList = value;
}
get
{
return _ruleIdList;
}
}
}
}
配置文件(RuleEngine.config )
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<defaultErrorCode>500</defaultErrorCode>
<!--Rule Type Definition: Fixed, Do not change-->
<ruleType>
<type id="1" name="IsNullOrEmpty"></type>
<type id="2" name="MinLength"></type>
<type id="3" name="MaxLength"></type>
<type id="4" name="Pattern"></type>
<type id="5" name="HasSpace"></type>
</ruleType>
<!--Rules Configuration: id and type are required attributes-->
<rules>
<!--Email Validation-->
<rule id="1" name="EmailNotEmpty" type="1" errorCode="-712"></rule>
<rule id="2" name="EmailPattern" type="4" errorCode="-710" value="^([\\w-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([\\w-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$"></rule>
<!--UserName Validation-->
<rule id="3" name="UserNameNotEmpty" type="1" errorCode="-778"></rule>
<rule id="4" name="UserNamePattern" type="4" errorCode="-707" value="^[-._a-zA-Z0-9]+$"></rule>
<rule id="5" name="MinUserNameLength" type="2" errorCode="-706" value="4"></rule>
<rule id="6" name="MaxUserNameLength" type="3" errorCode="-705" value="20"></rule>
<!--Password Validation-->
<rule id="7" name="UserPasswordNotEmpty" type="1" errorCode="-714"></rule>
<rule id="8" name="UserPasswordSpace" type="5" errorCode="-717"></rule>
<rule id="9" name="UserPasswordPattern" type="4" errorCode="-748" value="^((\\d+)|([!-/:-@\\[-`{-~]+)|(\\d+[a-zA-Z]+|[a-zA-Z]+\\d+)([\\da-zA-A]*)|([!-/:-@\\[-`{-~]+[a-zA-Z]+|[a-zA-Z]+[!-/:-@\\[-`{-~]+)([a-zA-Z!-/:-@\\[-`{-~]*)|(\\d+[a-zA-Z]+[!-/:-@\\[-`{-~]+|\\d+[!-/:-@\\[-`{-~]+[a-zA-Z]+|[a-zA-Z]+\\d+[!-/:-@\\[-`{-~]+|[a-zA-Z]+[!-/:-@\\[-`{-~]+\\d+|[!-/:-@\\[-`{-~]+[a-zA-Z]+\\d+|[!-/:-@\\[-`{-~]+\\d+[a-zA-Z]+)([\\da-zA-Z!-/:-@\\[-`{-~]*))$"></rule>
<rule id="10" name="MinUserPasswordLength" type="2" errorCode="-715" value="6"></rule>
<rule id="11" name="MaxUserPasswordLength" type="3" errorCode="-716" value="16"></rule>
<!--User Profile Validation-->
<rule id="12" name="UserDobNotEmpty" type="1" errorCode="-720"></rule>
<rule id="13" name="UserDobPattern" type="4" errorCode="-721" value="^[12]\\d{3}-(0?[1-9]|1[0-2])-(0?[1-9]|[1-2]\\d|3[01])$"></rule>
<rule id="14" name="UserCountryNotEmpty" type="1" errorCode="-724"></rule>
<rule id="15" name="UserLanguageNotEmpty" type="1" errorCode="-727"></rule>
<rule id="16" name="UserTosVersionNotEmpty" type="1" errorCode="-729"></rule>
<rule id="17" name="UserStatusNotEmpty" type="1" errorCode="-731"></rule>
<!--Persona Profile Validation-->
<rule id="18" name="PersonaDisplayNameNotEmpty" type="1" errorCode="-761"></rule>
<rule id="19" name="MinPersonaDisplayNameLength" type="1" errorCode="-764"></rule>
<rule id="20" name="MaxPersonaDisplayNameLength" type="1" errorCode="-763"></rule>
<rule id="21" name="PersonaDisplayNamePattern" type="4" errorCode="-1803" value="^[-._a-zA-Z0-9]+$"></rule>
<rule id="22" name="PersonaStatusNotEmpty" type="1" errorCode="-766"></rule>
</rules>
<!--Rule Set Configuration: do not add comments in ruleSets node-->
<ruleSets>
<set id="userEmail">
<rule id="1"></rule>
<rule id="2"></rule>
</set>
<set id="userName">
<rule id="3"></rule>
<rule id="4"></rule>
<rule id="5"></rule>
<rule id="6"></rule>
</set>
<set id="userPassword">
<rule id="7"></rule>
<rule id="8"></rule>
<rule id="9"></rule>
<rule id="10"></rule>
<rule id="11"></rule>
</set>
<set id="userDob">
<rule id="12"></rule>
<rule id="13"></rule>
</set>
<set id="userCountry">
<rule id="14"></rule>
</set>
<set id="userLanguage">
<rule id="15"></rule>
</set>
<set id="userTosVersion">
<rule id="16"></rule>
</set>
<set id="userStatus">
<rule id="17"></rule>
</set>
<set id="personaName">
<rule id="18"></rule>
<rule id="19"></rule>
<rule id="20"></rule>
<rule id="21"></rule>
</set>
<set id="personaStatus">
<rule id="22"></rule>
</set>
</ruleSets>
</configuration>
<configuration>
<defaultErrorCode>500</defaultErrorCode>
<!--Rule Type Definition: Fixed, Do not change-->
<ruleType>
<type id="1" name="IsNullOrEmpty"></type>
<type id="2" name="MinLength"></type>
<type id="3" name="MaxLength"></type>
<type id="4" name="Pattern"></type>
<type id="5" name="HasSpace"></type>
</ruleType>
<!--Rules Configuration: id and type are required attributes-->
<rules>
<!--Email Validation-->
<rule id="1" name="EmailNotEmpty" type="1" errorCode="-712"></rule>
<rule id="2" name="EmailPattern" type="4" errorCode="-710" value="^([\\w-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([\\w-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$"></rule>
<!--UserName Validation-->
<rule id="3" name="UserNameNotEmpty" type="1" errorCode="-778"></rule>
<rule id="4" name="UserNamePattern" type="4" errorCode="-707" value="^[-._a-zA-Z0-9]+$"></rule>
<rule id="5" name="MinUserNameLength" type="2" errorCode="-706" value="4"></rule>
<rule id="6" name="MaxUserNameLength" type="3" errorCode="-705" value="20"></rule>
<!--Password Validation-->
<rule id="7" name="UserPasswordNotEmpty" type="1" errorCode="-714"></rule>
<rule id="8" name="UserPasswordSpace" type="5" errorCode="-717"></rule>
<rule id="9" name="UserPasswordPattern" type="4" errorCode="-748" value="^((\\d+)|([!-/:-@\\[-`{-~]+)|(\\d+[a-zA-Z]+|[a-zA-Z]+\\d+)([\\da-zA-A]*)|([!-/:-@\\[-`{-~]+[a-zA-Z]+|[a-zA-Z]+[!-/:-@\\[-`{-~]+)([a-zA-Z!-/:-@\\[-`{-~]*)|(\\d+[a-zA-Z]+[!-/:-@\\[-`{-~]+|\\d+[!-/:-@\\[-`{-~]+[a-zA-Z]+|[a-zA-Z]+\\d+[!-/:-@\\[-`{-~]+|[a-zA-Z]+[!-/:-@\\[-`{-~]+\\d+|[!-/:-@\\[-`{-~]+[a-zA-Z]+\\d+|[!-/:-@\\[-`{-~]+\\d+[a-zA-Z]+)([\\da-zA-Z!-/:-@\\[-`{-~]*))$"></rule>
<rule id="10" name="MinUserPasswordLength" type="2" errorCode="-715" value="6"></rule>
<rule id="11" name="MaxUserPasswordLength" type="3" errorCode="-716" value="16"></rule>
<!--User Profile Validation-->
<rule id="12" name="UserDobNotEmpty" type="1" errorCode="-720"></rule>
<rule id="13" name="UserDobPattern" type="4" errorCode="-721" value="^[12]\\d{3}-(0?[1-9]|1[0-2])-(0?[1-9]|[1-2]\\d|3[01])$"></rule>
<rule id="14" name="UserCountryNotEmpty" type="1" errorCode="-724"></rule>
<rule id="15" name="UserLanguageNotEmpty" type="1" errorCode="-727"></rule>
<rule id="16" name="UserTosVersionNotEmpty" type="1" errorCode="-729"></rule>
<rule id="17" name="UserStatusNotEmpty" type="1" errorCode="-731"></rule>
<!--Persona Profile Validation-->
<rule id="18" name="PersonaDisplayNameNotEmpty" type="1" errorCode="-761"></rule>
<rule id="19" name="MinPersonaDisplayNameLength" type="1" errorCode="-764"></rule>
<rule id="20" name="MaxPersonaDisplayNameLength" type="1" errorCode="-763"></rule>
<rule id="21" name="PersonaDisplayNamePattern" type="4" errorCode="-1803" value="^[-._a-zA-Z0-9]+$"></rule>
<rule id="22" name="PersonaStatusNotEmpty" type="1" errorCode="-766"></rule>
</rules>
<!--Rule Set Configuration: do not add comments in ruleSets node-->
<ruleSets>
<set id="userEmail">
<rule id="1"></rule>
<rule id="2"></rule>
</set>
<set id="userName">
<rule id="3"></rule>
<rule id="4"></rule>
<rule id="5"></rule>
<rule id="6"></rule>
</set>
<set id="userPassword">
<rule id="7"></rule>
<rule id="8"></rule>
<rule id="9"></rule>
<rule id="10"></rule>
<rule id="11"></rule>
</set>
<set id="userDob">
<rule id="12"></rule>
<rule id="13"></rule>
</set>
<set id="userCountry">
<rule id="14"></rule>
</set>
<set id="userLanguage">
<rule id="15"></rule>
</set>
<set id="userTosVersion">
<rule id="16"></rule>
</set>
<set id="userStatus">
<rule id="17"></rule>
</set>
<set id="personaName">
<rule id="18"></rule>
<rule id="19"></rule>
<rule id="20"></rule>
<rule id="21"></rule>
</set>
<set id="personaStatus">
<rule id="22"></rule>
</set>
</ruleSets>
</configuration>
配置信息缓存类(RuleEngine_ConfigCache.cs)
using System;
using System.IO;
using System.Xml;
using EA.Common.Util;
namespace Rule
{
/// <summary>
/// Config Cache Class used for cache config file
/// </summary>
public class ConfigCache
{
/// <summary>
/// Config Name: this value is defined in Web Config file, used for define RuleEngine configue file name
/// </summary>
private const string _configName = "RuleEngine";
/// <summary>
/// Full File Name
/// </summary>
private static string _fullFileName = "";
/// <summary>
/// Config file root node name
/// </summary>
private const string _root = "configuration";
/// <summary>
/// FileInfo used for check file change
/// </summary>
private static FileInfo _fileInfo;
/// <summary>
/// Last check
/// </summary>
private static DateTime _lastCheck;
/// <summary>
/// last modify time of config file
/// </summary>
private static DateTime _lastModified;
/// <summary>
/// Default Error Code will throw when checking a rule fail and set ThrowExceptionCodeDirectly to true
/// </summary>
private static string _defaultErrorCode;
public static string DefaultErrorCode
{
set
{
_defaultErrorCode = value;
}
get
{
return _defaultErrorCode;
}
}
/// <summary>
/// Rule Array
/// </summary>
private static Rule[] _ruleArray;
public static Rule[] RuleArray
{
set
{
_ruleArray = value;
}
get
{
return _ruleArray;
}
}
/// <summary>
/// Rule Set Array
/// </summary>
private static RuleSet[] _ruleSetArray;
public static RuleSet[] RuleSetArray
{
set
{
_ruleSetArray = value;
}
get
{
return _ruleSetArray;
}
}
/// <summary>
/// Static Constructor
/// </summary>
static ConfigCache()
{
string fileName = ServiceConfiguration.GetInstance().GetAppSetting(_configName);
string filePath = AppDomain.CurrentDomain.BaseDirectory + "\\";
_fullFileName = filePath + fileName;
_fileInfo = new FileInfo(_fullFileName);
Load();
_lastModified = GetLastModified();
_lastCheck = DateTime.Now;
}
/// <summary>
/// Load config data from xml file
/// </summary>
private static void Load()
{
XmlDocument doc = new XmlDocument();
doc.Load(_fullFileName);
if (doc != null)
{
//Load DefaultErrorCode
XmlNode ruleNode = doc.SelectSingleNode("/" + _root + "/defaultErrorCode");
if (ruleNode!=null)
{
_defaultErrorCode = ruleNode.InnerText;
}
//Load Rule List
_ruleArray = GetRuleList(doc);
//Load Rule Set List
_ruleSetArray = GetRuleSetList(doc);
}
}
/// <summary>
/// Get arrtibute name of XmlNode object
/// </summary>
/// <param name="attName"></param>
/// <returns></returns>
private static string GetAttribute(XmlNode node, string attName)
{
if (node != null && node.Attributes[attName]!=null)
{
return node.Attributes[attName].Value;
}
return null;
}
/// <summary>
/// Get Rule List
/// </summary>
/// <param name="doc"></param>
/// <returns></returns>
private static Rule[] GetRuleList(XmlDocument doc)
{
Rule[] array = null;
XmlNode ruleNode = doc.SelectSingleNode("/" + _root + "/rules");
if (ruleNode.ChildNodes.Count > 0)
{
array = new Rule[ruleNode.ChildNodes.Count];
Rule rule;
int index = 0;
for (int i = 0; i < ruleNode.ChildNodes.Count; i++)
{
//skip comment
if (ruleNode.ChildNodes[i].NodeType == XmlNodeType.Comment)
{
continue;
}
rule = new Rule();
rule.ID = GetAttribute(ruleNode.ChildNodes[i],"id");
rule.Name = GetAttribute(ruleNode.ChildNodes[i],"name");
string strType = GetAttribute(ruleNode.ChildNodes[i],"type");
if (!String.IsNullOrEmpty(strType))
{
rule.Type = (RuleType)Enum.Parse(typeof(RuleType), strType);
}
string strIsNot = GetAttribute(ruleNode.ChildNodes[i],"isNot");
if (!String.IsNullOrEmpty(strIsNot))
{
rule.IsNot = Boolean.Parse(strIsNot);
}
rule.ErrorCode = GetAttribute(ruleNode.ChildNodes[i],"errorCode");
rule.Value = GetAttribute(ruleNode.ChildNodes[i], "value");
array[index] = rule;
index++;
}
}
return array;
}
/// <summary>
/// Get Rule Set List
/// </summary>
/// <param name="doc"></param>
/// <returns></returns>
private static RuleSet[] GetRuleSetList(XmlDocument doc)
{
RuleSet[] setArray = null;
XmlNode setNode = doc.SelectSingleNode("/" + _root + "/ruleSets");
if (setNode.ChildNodes.Count > 0)
{
setArray = new RuleSet[setNode.ChildNodes.Count];
RuleSet set;
for (int i = 0; i < setNode.ChildNodes.Count; i++)
{
XmlNode ruleNode = setNode.ChildNodes[i];
//skip comment
if (ruleNode.NodeType == XmlNodeType.Comment)
{
continue;
}
set = new RuleSet();
set.SetId = GetAttribute(ruleNode,"id");
if (ruleNode.ChildNodes.Count > 0)
{
set.RuleIdList = new string[ruleNode.ChildNodes.Count];
for (int j = 0; j < ruleNode.ChildNodes.Count; j++)
{
//skip comment
if (ruleNode.ChildNodes[j].NodeType == XmlNodeType.Comment)
{
continue;
}
set.RuleIdList[j] = GetAttribute(ruleNode.ChildNodes[j],"id");
}
}
setArray[i] = set;
}
}
return setArray;
}
/// <summary>
/// Get tule object by rule id
/// </summary>
/// <param name="ruleId"></param>
public static Rule GetRule(string ruleId)
{
Rule result = null;
if (_ruleArray != null)
{
for (int i = 0; i < _ruleArray.Length; i++)
{
if (_ruleArray[i].ID == ruleId)
{
result = _ruleArray[i];
break;
}
}
}
return result;
}
/// <summary>
/// Get rule set object by set id
/// </summary>
/// <param name="setId"></param>
public static RuleSet GetRuleSet(string setId)
{
CheckFileChanged();
RuleSet result = null;
if (_ruleSetArray != null)
{
for (int i = 0; i < _ruleSetArray.Length; i++)
{
if (_ruleSetArray[i].SetId == setId)
{
result = _ruleSetArray[i];
break;
}
if (i==(_ruleSetArray.Length-1))
{
throw new Exception("RuleEngine can't find set id:" + setId);
}
}
}
return result;
}
/// <summary>
/// if config file changed, invoke this method will reload config data from disk
/// </summary>
private static void CheckFileChanged()
{
//Less than 10mins, do not check
if (DateTime.Now.Subtract(_lastCheck).Minutes < 10)
{
return;
}
DateTime check = GetLastModified();
if (_lastModified != check)
{
Load();
_lastModified = check;
_lastCheck = DateTime.Now;
}
}
/// <summary>
/// Get last modify time of config file
/// </summary>
/// <returns></returns>
private static DateTime GetLastModified()
{
_fileInfo.Refresh();
return _fileInfo.LastWriteTime;
}
}
}
using System.IO;
using System.Xml;
using EA.Common.Util;
namespace Rule
{
/// <summary>
/// Config Cache Class used for cache config file
/// </summary>
public class ConfigCache
{
/// <summary>
/// Config Name: this value is defined in Web Config file, used for define RuleEngine configue file name
/// </summary>
private const string _configName = "RuleEngine";
/// <summary>
/// Full File Name
/// </summary>
private static string _fullFileName = "";
/// <summary>
/// Config file root node name
/// </summary>
private const string _root = "configuration";
/// <summary>
/// FileInfo used for check file change
/// </summary>
private static FileInfo _fileInfo;
/// <summary>
/// Last check
/// </summary>
private static DateTime _lastCheck;
/// <summary>
/// last modify time of config file
/// </summary>
private static DateTime _lastModified;
/// <summary>
/// Default Error Code will throw when checking a rule fail and set ThrowExceptionCodeDirectly to true
/// </summary>
private static string _defaultErrorCode;
public static string DefaultErrorCode
{
set
{
_defaultErrorCode = value;
}
get
{
return _defaultErrorCode;
}
}
/// <summary>
/// Rule Array
/// </summary>
private static Rule[] _ruleArray;
public static Rule[] RuleArray
{
set
{
_ruleArray = value;
}
get
{
return _ruleArray;
}
}
/// <summary>
/// Rule Set Array
/// </summary>
private static RuleSet[] _ruleSetArray;
public static RuleSet[] RuleSetArray
{
set
{
_ruleSetArray = value;
}
get
{
return _ruleSetArray;
}
}
/// <summary>
/// Static Constructor
/// </summary>
static ConfigCache()
{
string fileName = ServiceConfiguration.GetInstance().GetAppSetting(_configName);
string filePath = AppDomain.CurrentDomain.BaseDirectory + "\\";
_fullFileName = filePath + fileName;
_fileInfo = new FileInfo(_fullFileName);
Load();
_lastModified = GetLastModified();
_lastCheck = DateTime.Now;
}
/// <summary>
/// Load config data from xml file
/// </summary>
private static void Load()
{
XmlDocument doc = new XmlDocument();
doc.Load(_fullFileName);
if (doc != null)
{
//Load DefaultErrorCode
XmlNode ruleNode = doc.SelectSingleNode("/" + _root + "/defaultErrorCode");
if (ruleNode!=null)
{
_defaultErrorCode = ruleNode.InnerText;
}
//Load Rule List
_ruleArray = GetRuleList(doc);
//Load Rule Set List
_ruleSetArray = GetRuleSetList(doc);
}
}
/// <summary>
/// Get arrtibute name of XmlNode object
/// </summary>
/// <param name="attName"></param>
/// <returns></returns>
private static string GetAttribute(XmlNode node, string attName)
{
if (node != null && node.Attributes[attName]!=null)
{
return node.Attributes[attName].Value;
}
return null;
}
/// <summary>
/// Get Rule List
/// </summary>
/// <param name="doc"></param>
/// <returns></returns>
private static Rule[] GetRuleList(XmlDocument doc)
{
Rule[] array = null;
XmlNode ruleNode = doc.SelectSingleNode("/" + _root + "/rules");
if (ruleNode.ChildNodes.Count > 0)
{
array = new Rule[ruleNode.ChildNodes.Count];
Rule rule;
int index = 0;
for (int i = 0; i < ruleNode.ChildNodes.Count; i++)
{
//skip comment
if (ruleNode.ChildNodes[i].NodeType == XmlNodeType.Comment)
{
continue;
}
rule = new Rule();
rule.ID = GetAttribute(ruleNode.ChildNodes[i],"id");
rule.Name = GetAttribute(ruleNode.ChildNodes[i],"name");
string strType = GetAttribute(ruleNode.ChildNodes[i],"type");
if (!String.IsNullOrEmpty(strType))
{
rule.Type = (RuleType)Enum.Parse(typeof(RuleType), strType);
}
string strIsNot = GetAttribute(ruleNode.ChildNodes[i],"isNot");
if (!String.IsNullOrEmpty(strIsNot))
{
rule.IsNot = Boolean.Parse(strIsNot);
}
rule.ErrorCode = GetAttribute(ruleNode.ChildNodes[i],"errorCode");
rule.Value = GetAttribute(ruleNode.ChildNodes[i], "value");
array[index] = rule;
index++;
}
}
return array;
}
/// <summary>
/// Get Rule Set List
/// </summary>
/// <param name="doc"></param>
/// <returns></returns>
private static RuleSet[] GetRuleSetList(XmlDocument doc)
{
RuleSet[] setArray = null;
XmlNode setNode = doc.SelectSingleNode("/" + _root + "/ruleSets");
if (setNode.ChildNodes.Count > 0)
{
setArray = new RuleSet[setNode.ChildNodes.Count];
RuleSet set;
for (int i = 0; i < setNode.ChildNodes.Count; i++)
{
XmlNode ruleNode = setNode.ChildNodes[i];
//skip comment
if (ruleNode.NodeType == XmlNodeType.Comment)
{
continue;
}
set = new RuleSet();
set.SetId = GetAttribute(ruleNode,"id");
if (ruleNode.ChildNodes.Count > 0)
{
set.RuleIdList = new string[ruleNode.ChildNodes.Count];
for (int j = 0; j < ruleNode.ChildNodes.Count; j++)
{
//skip comment
if (ruleNode.ChildNodes[j].NodeType == XmlNodeType.Comment)
{
continue;
}
set.RuleIdList[j] = GetAttribute(ruleNode.ChildNodes[j],"id");
}
}
setArray[i] = set;
}
}
return setArray;
}
/// <summary>
/// Get tule object by rule id
/// </summary>
/// <param name="ruleId"></param>
public static Rule GetRule(string ruleId)
{
Rule result = null;
if (_ruleArray != null)
{
for (int i = 0; i < _ruleArray.Length; i++)
{
if (_ruleArray[i].ID == ruleId)
{
result = _ruleArray[i];
break;
}
}
}
return result;
}
/// <summary>
/// Get rule set object by set id
/// </summary>
/// <param name="setId"></param>
public static RuleSet GetRuleSet(string setId)
{
CheckFileChanged();
RuleSet result = null;
if (_ruleSetArray != null)
{
for (int i = 0; i < _ruleSetArray.Length; i++)
{
if (_ruleSetArray[i].SetId == setId)
{
result = _ruleSetArray[i];
break;
}
if (i==(_ruleSetArray.Length-1))
{
throw new Exception("RuleEngine can't find set id:" + setId);
}
}
}
return result;
}
/// <summary>
/// if config file changed, invoke this method will reload config data from disk
/// </summary>
private static void CheckFileChanged()
{
//Less than 10mins, do not check
if (DateTime.Now.Subtract(_lastCheck).Minutes < 10)
{
return;
}
DateTime check = GetLastModified();
if (_lastModified != check)
{
Load();
_lastModified = check;
_lastCheck = DateTime.Now;
}
}
/// <summary>
/// Get last modify time of config file
/// </summary>
/// <returns></returns>
private static DateTime GetLastModified()
{
_fileInfo.Refresh();
return _fileInfo.LastWriteTime;
}
}
}