Very simple, your business entities should include a section for storing Business Validation (this is business logic). This will then work regardless of whether you are developing a web application, a client application, a mobile application, etc. Very flexible.
Suppose you have a business object (object), such as a client:
public class Customer { public Customer(int customerId, string company, string city, string country) { CustomerId = customerId; Company = company; City = city; Country = country; } }
Then you understand that you want your business logic to indicate that you are checking the customer identifier (in addition, it is> 0), you need the name of the company (it is not valid without one client), etc. These checks are your level of business logic. Thus, you can change your client class to inherit using the BusinessObject layer so that your class becomes the following:
public class Customer : BusinessObject {
You do not need objects of type BusinessObject, but which business object serves as an abstract class that stores validation errors and business rules. A business rule is ultimately the rule that you specified when you called AddRule:
public abstract class BusinessObject {
Each business rule, such as validateid, validaterequired, and validatelength, must be implemented:
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; } }
These are just two samples validatelength and validateid, you can come up with validaterequired (check if this value exists). They both implement the business rule class:
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 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); } }
Thus, your business class simply keeps a list of the necessary business rules and validation errors that it catches. The business rule class simply saves the property name and error message if the rule is not applied correctly. It also contains the abstract validate () method, which is defined for each validation class. It is different for each validation class, because validating the identifier is different and then validating the correct field.
The gang of four websites has a lot of good help in this regard. Most of this code is taken from their models.