You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在FluentValidation中为未指定规则的属性设置默认验证规则?

How to Set Default Validation Rules in FluentValidation for Unspecified Properties

Absolutely! You can set up default validation rules for properties that don't have explicit rules defined in FluentValidation. For your MyClass scenario—where Bar needs a specific NotNull() rule (allowing empty strings) and all other string properties (Foo, Baz) should use NotEmpty()—here's a clean, maintainable way to pull it off:

Step 1: Keep Your Class Definition

First, your existing class stays exactly as is:

public class MyClass 
{ 
    public string Foo { get; set; } 
    public string Bar { get; set; } 
    public string Baz { get; set; } 
}

Step 2: Build a Validator with Automatic Default Rules

Instead of manually adding NotEmpty() to every string property except Bar, we'll create a validator that automatically applies the default rule to any unconfigured string properties. Here's the implementation:

using FluentValidation;
using System.Linq;
using System.Reflection;
using System.Linq.Expressions;

public class MyClassValidator : AbstractValidator<MyClass>
{
    public MyClassValidator()
    {
        // First, define your explicit, property-specific rule for Bar
        RuleFor(c => c.Bar).NotNull();

        // Get names of all properties that already have rules configured
        var configuredProps = Descriptor.GetMembersWithRules()
            .Select(member => member.Member.Name)
            .ToHashSet();

        // Grab all string properties on MyClass that don't have explicit rules
        var unconfiguredStringProps = typeof(MyClass).GetProperties()
            .Where(prop => prop.PropertyType == typeof(string) && !configuredProps.Contains(prop.Name))
            .Select(prop => prop.Name);

        // Apply the default NotEmpty() rule to each unconfigured property
        foreach (var propName in unconfiguredStringProps)
        {
            // Dynamically build the lambda expression needed for RuleFor
            var param = Expression.Parameter(typeof(MyClass), "c");
            var property = Expression.Property(param, propName);
            var ruleExpression = Expression.Lambda<Func<MyClass, string>>(property, param);

            RuleFor(ruleExpression).NotEmpty();
        }
    }
}

How This Works

Let's break down the logic:

  1. Explicit Rules First: We start with the specific rule for Bar—this ensures it gets excluded from the default rule logic.
  2. Track Configured Properties: Using the validator's Descriptor property, we pull out all properties that already have rules attached.
  3. Find Unconfigured String Properties: We use reflection to get all string properties on MyClass, then filter out any that already have explicit rules.
  4. Apply Default Rule: For each unconfigured property, we dynamically create the lambda expression needed for RuleFor and attach the NotEmpty() rule.

Bonus: Reusable Extension Method

If you want to reuse this default rule logic across multiple validators, wrap it in an extension method:

public static class ValidatorExtensions
{
    public static void ApplyDefaultStringNotEmptyRule<T>(this AbstractValidator<T> validator)
    {
        var configuredProps = validator.Descriptor.GetMembersWithRules()
            .Select(member => member.Member.Name)
            .ToHashSet();

        var unconfiguredStringProps = typeof(T).GetProperties()
            .Where(prop => prop.PropertyType == typeof(string) && !configuredProps.Contains(prop.Name))
            .Select(prop => prop.Name);

        foreach (var propName in unconfiguredStringProps)
        {
            var param = Expression.Parameter(typeof(T), "c");
            var property = Expression.Property(param, propName);
            var ruleExpression = Expression.Lambda<Func<T, string>>(property, param);

            validator.RuleFor(ruleExpression).NotEmpty();
        }
    }
}

Then use it in your validator like this:

public MyClassValidator()
{
    RuleFor(c => c.Bar).NotNull();
    this.ApplyDefaultStringNotEmptyRule();
}

Key Notes

  • Order Matters: Always define your explicit rules before applying the default rule logic—this ensures explicit rules take precedence.
  • Reflection Overhead: This approach uses reflection, which has minimal performance impact for most business scenarios. For high-throughput environments, consider caching the property lookup results.
  • Flexibility: Adjust the default rule (e.g., switch to NotNull()) or expand the property filter (e.g., include value types) to fit your specific needs.

内容的提问来源于stack exchange,提问作者Andrew Cooper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:14:26