我正在寻找任何推荐的验证框架或N层客户端应用程序的模式,我想编写验证方法一次并将其绑定到WPF GUI,如果可能的话还要用于服务器端和客户端相关商业逻辑。
答案 0 :(得分:3)
很简单,您的业务实体应该包含一个用于存储业务验证的部分(即业务逻辑)。无论您是设计基于Web的应用程序,基于客户端的应用程序,移动应用程序等,这都将起作用。非常灵活。
假设您有一个像客户一样的业务对象(实体):
public class Customer
{
public Customer(int customerId, string company, string city, string country)
{
CustomerId = customerId;
Company = company;
City = city;
Country = country;
}
}
然后您意识到您希望您的业务逻辑声明您验证了customerID(此外它是> 0),您需要公司名称(没有客户无效)等等。这些验证是您的业务逻辑层。因此,您可以将您的客户类更改为继承BusinessObject图层,以便您的类成为:
public class Customer : BusinessObject
{
/// <summary>
/// Default constructor for customer class.
/// Initializes automatic properties.
/// </summary>
public Customer()
{
// Default property values
Orders = new List<Order>();
// Business rules
AddRule(new ValidateId("CustomerId"));
AddRule(new ValidateRequired("Company"));
AddRule(new ValidateLength("Company", 1, 40));
}
/// <summary>
/// Overloaded constructor for the Customer class.
/// </summary>
/// <param name="customerId">Unique Identifier for the Customer.</param>
/// <param name="company">Name of the Customer.</param>
/// <param name="city">City where Customer is located.</param>
/// <param name="country">Country where Customer is located.</param>
public Customer(int customerId, string company, string city, string country)
: this()
{
CustomerId = customerId;
Company = company;
City = city;
Country = country;
}
//much more code like methods...
}
您不需要BusinessObject类型的对象,但是businessobject用作存储验证错误和业务规则的抽象类。业务规则最终是您在调用AddRule时所声明的规则:
public abstract class BusinessObject
{
/// <summary>
/// Default value for version number (used in LINQ's optimistic concurrency)
/// </summary>
protected static readonly string _versionDefault = "NotSet";
// List of business rules
private IList<BusinessRule> _businessRules = new List<BusinessRule>();
// List of validation errors (following validation failure)
private IList<string> _validationErrors = new List<string>();
/// <summary>
/// Gets list of validations errors.
/// </summary>
public IList<string> ValidationErrors
{
get { return _validationErrors; }
}
/// <summary>
/// Adds a business rule to the business object.
/// </summary>
/// <param name="rule"></param>
protected void AddRule(BusinessRule rule)
{
_businessRules.Add(rule);
}
/// <summary>
/// Determines whether business rules are valid or not.
/// Creates a list of validation errors when appropriate.
/// </summary>
/// <returns></returns>
public bool Validate()
{
bool isValid = true;
_validationErrors.Clear();
foreach (BusinessRule rule in _businessRules)
{
if (!rule.Validate(this))
{
isValid = false;
_validationErrors.Add(rule.ErrorMessage);
}
}
return isValid;
}
}
需要实现每个业务规则,例如validateid,validaterequired和validatelength:
public class ValidateId : BusinessRule
{
public ValidateId(string propertyName)
: base(propertyName)
{
ErrorMessage = propertyName + " is an invalid identifier";
}
public ValidateId(string propertyName, string errorMessage)
: base(propertyName)
{
ErrorMessage = errorMessage;
}
public override bool Validate(BusinessObject businessObject)
{
try
{
int id = int.Parse(GetPropertyValue(businessObject).ToString());
return id >= 0;
}
catch
{
return false;
}
}
public class ValidateLength : BusinessRule
{
private int _min;
private int _max;
public ValidateLength(string propertyName, int min, int max)
: base(propertyName)
{
_min = min;
_max = max;
ErrorMessage = propertyName + " must be between " + _min + " and " + _max + " characters long.";
}
public ValidateLength(string propertyName, string errorMessage, int min, int max)
: this(propertyName, min, max)
{
ErrorMessage = errorMessage;
}
public override bool Validate(BusinessObject businessObject)
{
int length = GetPropertyValue(businessObject).ToString().Length;
return length >= _min && length <= _max;
}
}
这只是validatelength的两个示例,而validateid,你可以提出validaterequired(检查值是否存在)。它们都实现了业务规则类:
public abstract class BusinessRule
{
public string PropertyName { get; set; }
public string ErrorMessage { get; set; }
/// <summary>
/// Constructor
/// </summary>
/// <param name="propertyName">The property name to which rule applies.</param>
public BusinessRule(string propertyName)
{
PropertyName = propertyName;
ErrorMessage = propertyName + " is not valid";
}
/// <summary>
/// Overloaded constructor
/// </summary>
/// <param name="propertyName">The property name to which rule applies.</param>
/// <param name="errorMessage">The error message.</param>
public BusinessRule(string propertyName, string errorMessage)
: this(propertyName)
{
ErrorMessage = errorMessage;
}
/// <summary>
/// Validation method. To be implemented in derived classes.
/// </summary>
/// <param name="businessObject"></param>
/// <returns></returns>
public abstract bool Validate(BusinessObject businessObject);
/// <summary>
/// Gets value for given business object's property using reflection.
/// </summary>
/// <param name="businessObject"></param>
/// <param name="propertyName"></param>
/// <returns></returns>
protected object GetPropertyValue(BusinessObject businessObject)
{
return businessObject.GetType().GetProperty(PropertyName).GetValue(businessObject, null);
}
}
因此,您的businessobject类只保留所需业务规则及其捕获的验证错误的列表。业务规则类仅存储属性名称和错误消息,以防未正确应用规则。它还包含一个为每个验证类定义的抽象validate()方法。它对于每个验证类都不同,因为验证id与验证必填字段不同。
四人帮网站对此有很多好的帮助。大部分代码都来自他们的模型。
答案 1 :(得分:1)
对codeplex的简单搜索会返回许多验证框架。许多人采用与JonH提到的非常相似的技术。类似于。net Validation framework的东西似乎符合您的标准。