2010-03-25 6 views
3

N-tier 클라이언트 응용 프로그램의 권장 유효성 검사 프레임 워크 또는 패턴을 찾고 있는데 유효성 검사 메서드를 한 번 작성하고 WPF GUI에 바인딩하고 가능하면 서버 측면 및 클라이언트 측 관련 비즈니스 논리..net에서 데이터 유효성 검사

+0

@Chen Kinnrot - 더 자세한 정보가 필요하거나 우리가 답변을 표시 할만큼 충분히 제공 했습니까? – JonH

답변

3

매우 간단하게 비즈니스 엔티티에는 비즈니스 유효성 검사 (비즈니스 로직)를 저장하는 섹션이 포함되어야합니다. 그러면 웹 기반 응용 프로그램, 클라이언트 기반 응용 프로그램, 모바일 응용 프로그램 등을 디자인 할 때 매우 효과적입니다. 매우 유연합니다.

당신이 고객의 입장에서 비즈니스 객체 (엔티티)가 가정 :

public class Customer 
{ 
     public Customer(int customerId, string company, string city, string country) 
     { 
      CustomerId = customerId; 
      Company = company; 
      City = city; 
      Country = country; 
     } 
    } 

당신은 당신이 당신의 비즈니스 로직은 당신이 (추가로이> 0)는 고객 ID를 확인한다는 것은 원하는 것을 실현, 당신은 회사 이름 (고객이 유효하지 않은 경우)이 필요합니다. 등등이 검증은 비즈니스 로직 레이어입니다. 유효성 검사 오류 등을 저장하는 추상 클래스와 같이

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는 제공 : 그래서 당신은 BusinessObject 층 말에서 상속하는 고객 클래스를 변경할 수 있습니다, 그래서 당신의 클래스는이됩니다 비즈니스 규칙. 비즈니스 규칙은 궁극적으로 AddRule 전화했을 때 당신이 언급 된 규칙입니다 : 같은 validateid 같은

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; 
    } 
} 

각 비즈니스 규칙, 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의 유효성이 다르거 나 유효성 검증이 필요한 필드이므로 유효성 검사 클래스마다 다릅니다.

네 개의 웹 사이트의 갱단은 이것에 관해 많은 도움을줍니다. 이 코드의 상당 부분은 모델에서 가져온 것입니다.

+0

만약 내가 최고의 성능을 위해 반사를 피하고 싶다면, 당신은 더 나은 것을 얻었습니까? –

+0

@Chen Kinnrot - 사용되는 유일한 리플렉션은 GetPropertyValue 내부입니다. 당신이 할 수있는 다른 일은 모든 유효성 검사 클래스를 없애고 각 속성에 대한 코드를 하드 코딩하는 것입니다. 하지만 제품 클래스에 대해 이것을 재사용 할 수는 없습니다. 앱이 간단하면 충분하다. – JonH

1

codeplex에서 간단한 검색을하면 많은 유효성 검사 프레임 워크가 반환됩니다. 많은 사람들이 JonH가 언급 한 것과 매우 유사한 기술을 사용합니다. 같은 것. net Validation framework 님이 내게 맞는 상품입니다.

관련 문제