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

Blazor中RegularExpression属性动态正则字符串重置问题求解

解决方案:Blazor动态修改正则验证规则

核心问题分析

你遇到的问题本质是:<DataAnnotationsValidator>在每次触发验证时,都会通过反射重新创建ValidationAttribute的实例,导致你之前通过Update方法修改的旧实例失效,新实例始终使用构造函数传入的原始正则表达式。

下面提供两种可行的解决方案,按需选择:


方案一:自定义支持动态正则的验证属性(推荐)

这种方式彻底摆脱属性实例状态依赖,将正则表达式存储在全局共享服务中,每次验证时实时获取最新规则。

1. 定义动态正则服务

// 接口定义
public interface IDynamicRegexProvider
{
    // 根据键获取当前正则表达式
    string GetPattern(string key);
    // 更新指定键的正则表达式
    void UpdatePattern(string key, string newPattern);
}

// 实现类(单例模式)
public class DynamicRegexProvider : IDynamicRegexProvider
{
    private readonly Dictionary<string, string> _patternStore = new(StringComparer.OrdinalIgnoreCase);

    public string GetPattern(string key)
    {
        _patternStore.TryGetValue(key, out var pattern);
        return pattern;
    }

    public void UpdatePattern(string key, string newPattern)
    {
        _patternStore[key] = newPattern;
    }
}

2. 注册服务

在Program.cs中添加单例注册:

builder.Services.AddSingleton<IDynamicRegexProvider>();

3. 创建动态正则验证属性

public class DynamicRegularExpressionAttribute : ValidationAttribute
{
    private readonly string _regexKey;

    public DynamicRegularExpressionAttribute(string regexKey)
    {
        _regexKey = regexKey;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        // 从服务获取最新正则
        var regexProvider = validationContext.GetService<IDynamicRegexProvider>();
        if (regexProvider == null) return ValidationResult.Success;

        var pattern = regexProvider.GetPattern(_regexKey);
        if (string.IsNullOrWhiteSpace(pattern)) return ValidationResult.Success;

        // 执行验证
        if (value != null && !System.Text.RegularExpressions.Regex.IsMatch(value.ToString(), pattern))
        {
            return new ValidationResult(ErrorMessage ?? $"输入格式不符合要求");
        }

        return ValidationResult.Success;
    }
}

4. 模型中使用属性

public class InputModel
{
    [DynamicRegularExpression("UserInputRegex", ErrorMessage = "格式不正确")]
    public string UserInput { get; set; }
}

5. 组件中动态修改正则并触发验证

@inject IDynamicRegexProvider RegexProvider
@inject EditContext EditContext

<EditForm Model="@_model" EditContext="@EditContext">
    <InputText @bind-Value="_model.UserInput" />
    <ValidationMessage For="@(() => _model.UserInput)" />

    <button @onclick="SwitchTo4DigitRegex">切换为4位数字验证</button>
    <button @onclick="SwitchToLetterRegex">切换为字母验证</button>
</EditForm>

@code {
    private InputModel _model = new();

    private void SwitchTo4DigitRegex()
    {
        RegexProvider.UpdatePattern("UserInputRegex", @"^\d{4}$");
        EditContext.Validate(); // 触发重新验证
    }

    private void SwitchToLetterRegex()
    {
        RegexProvider.UpdatePattern("UserInputRegex", @"^[A-Za-z]+$");
        EditContext.Validate();
    }
}

方案二:手动处理验证逻辑(兼容现有ValidationAttribute)

如果必须保留你提到的第三方ValidationAttribute派生类,可以绕过<DataAnnotationsValidator>,手动控制验证流程:

1. 组件代码

<EditForm Model="@_model" @ref="_editForm">
    <InputText @bind-Value="_model.Input" />
    <div class="text-danger">@_validationMessage</div>

    <button @onclick="UpdateRegexTo4Digit">修改为4位数字验证</button>
</EditForm>

@code {
    private EditForm _editForm;
    private InputModel _model = new();
    private string _currentRegex = @"^\d{3}$";
    private string _validationMessage = string.Empty;

    // 自定义验证方法
    private void ValidateInput()
    {
        _validationMessage = string.Empty;
        var inputValue = _model.Input;

        // 创建第三方验证属性实例,设置最新正则
        var validator = new YourThirdPartyRegexAttribute(_currentRegex);
        validator.Update(_currentRegex); // 调用第三方类的Update方法

        var result = validator.GetValidationResult(inputValue, new ValidationContext(_model));
        if (result != ValidationResult.Success)
        {
            _validationMessage = result.ErrorMessage;
        }
    }

    // 监听输入变化自动验证
    protected override void OnInitialized()
    {
        _editForm.EditContext.FieldChanged += (sender, e) =>
        {
            if (e.FieldIdentifier.FieldName == nameof(InputModel.Input))
            {
                ValidateInput();
            }
        };
    }

    // 修改正则并触发验证
    private void UpdateRegexTo4Digit()
    {
        _currentRegex = @"^\d{4}$";
        ValidateInput();
    }

    // 你的模型类(保留原有第三方属性,实际验证时不会用到)
    public class InputModel
    {
        [YourThirdPartyRegex(@"^\d{3}$")]
        public string Input { get; set; }
    }
}

注意事项

  • 移除组件中的<DataAnnotationsValidator>,避免与手动验证冲突
  • 所有验证逻辑由你完全控制,不会出现属性实例重置问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 04:57:12