IRuleSource Interface

Declares members implemented by custom Validation Rule Sources.

Namespace: DevExpress.Persistent.Validation

Assembly: DevExpress.Persistent.Base.v18.1.dll


public interface IRuleSource
Public Interface IRuleSource

There are several ways in which you can declare a Validation Rule. A typical way is to decorate a target business class with a Validation Rule Attribute. However, the Validation Module allows you to define a custom Validation Rule Source by implementing the IRuleSource interface in a business class. Classes that implement the IRuleSource interface are considered to be Validation Rule Sources by XAF, and are used to provide custom Validation Rules when the application is started. Custom Validation Rule Sources are collected automatically, and no registration is necessary.

The IRuleSource interface exposes two members. The IRuleSource.Name property should return the unique name of the custom Validation Rule Source. The IRuleSource.CreateRules method should instantiate custom Validation Rules.

One of the scenarios in which you may need to implement a custom Validation Rule Source is implementing Validation Rules stored in the database. This approach can be used when you need to frequently customize Validation Rules in a deployed application, but you cannot redeploy the application or customize its Application Model. The following example illustrates this scenario.


A complete sample project is available in the DevExpress Code Examples database at

The RuleRequiredFieldPersistent class demonstrated in this example is a regular business class. However, the class implements the IRuleSource interface, and is used to create and store RuleRequiredField Validation Rules in the database. In the IRuleSource.CreateRules method a RuleRequiredField Validation Rule is instantiated, based on the values of the RuleRequiredFieldPersistent class' public properties. The RuleRequiredFieldPersistent class is marked with the DefaultClassOptionsAttribute, so that end-users can manually create Validation Rules via a corresponding List View.

public class RuleRequiredFieldPersistent : BaseObject, 
    DevExpress.Persistent.Validation.IRuleSource {
    public RuleRequiredFieldPersistent(Session session) : base(session) { }
    public string RuleName {
        get { return GetPropertyValue<string>("RuleName"); }
        set { SetPropertyValue("RuleName", value); }
    public string CustomMessageTemplate {
        get { return GetPropertyValue<string>("CustomMessageTemplate"); }
        set { SetPropertyValue("CustomMessageTemplate", value); }
    public bool SkipNullOrEmptyValues {
        get { return GetPropertyValue<bool>("SkipNullOrEmptyValues"); }
        set { SetPropertyValue("SkipNullOrEmptyValues", value); }
    public string Id {
        get { return GetPropertyValue<string>("Id"); }
        set { SetPropertyValue("Id", value); }
    public bool InvertResult {
        get { return GetPropertyValue<bool>("InvertResult"); }
        set { SetPropertyValue("InvertResult", value); }
    public string ContextIDs {
        get { return GetPropertyValue<string>("ContextIDs"); }
        set { SetPropertyValue("ContextIDs", value); }
    public string Property {
        get { return GetPropertyValue<string>("Property"); }
        set { SetPropertyValue("Property", value); }
    protected string ObjectType {
        get {
            if(ObjectTypeCore != null) {
                return ObjectTypeCore.FullName;
            return "";
        set { ObjectTypeCore = ReflectionHelper.FindType(value); }
    public Type ObjectTypeCore {
        get { return GetPropertyValue<Type>("ObjectTypeCore"); }
        set { SetPropertyValue("ObjectTypeCore", value); }
    #region IRuleSource Members
    public System.Collections.Generic.ICollection<IRule> CreateRules() {
        System.Collections.Generic.List<IRule> list = new System.Collections.Generic.List<IRule>();
        RuleRequiredField rule = new RuleRequiredField();
        rule.Properties.SkipNullOrEmptyValues = this.SkipNullOrEmptyValues;
        rule.Properties.Id = this.Id;
        rule.Properties.InvertResult = this.InvertResult;
        rule.Properties.CustomMessageTemplate = this.CustomMessageTemplate;
        rule.Properties.TargetContextIDs = new ContextIdentifiers(this.ContextIDs);
        rule.Properties.TargetType = this.ObjectTypeCore;
        if(rule.Properties.TargetType != null) {
            foreach(PropertyInfo pi in rule.Properties.TargetType.GetProperties()) {
                if(pi.Name == this.Property) {
                    rule.Properties.TargetPropertyName = pi.Name;
        for(int i = Validator.RuleSet.RegisteredRules.Count - 1; i >= 0; i--) {
            if(Validator.RuleSet.RegisteredRules[i].Id == this.Id) {
        return list;
    public string Name {
        get { return this.RuleName; }

See Also