【问题标题】:How to Use defined Object instead of a string in C#?如何在 C# 中使用定义的对象而不是字符串?
【发布时间】:2016-10-22 07:21:34
【问题描述】:

我的模型类很少,我注意到 Name 属性(例如:CountryName、BranchName、StateName、 等)在整个应用程序中具有相同的规则,例如它必须是强制性的并且不能超过一定数量的字符。下面以BranchAddClass.cs为例。


问题:


  1. 如何在Model Class 代码中定义自定义对象并重用,而不是声明为字符串(参见BranchAddModel.cs 中的BranchName 属性)。
  2. 如何在 NameField.cs 中实施 FluentValidation 规则。目前,正在重复验证(请参阅BranchAddModel.cs 类)。

NameField.cs

我正在考虑创建一个对象类并在这个类中执行验证,这样我就不会违反DRY 原则。但我无法实现它。如果您有更好的方法来实现我想要实现的目标,我们将受到欢迎!

public class NameField
    {
        private readonly string _value;

        private NameField(string value)
        {
            _value = value;
        }
    }

如果 NameField 类有效,那么我希望我可以在应用程序的其余部分使用它,请参阅示例

BranchAddModel.cs

namespace Application
{
    [Validator(typeof(BranchAddModelValidator))]
    public class BranchAddModel
    {
        public byte ServiceTypeId { get; set; }
        public string BranchName { get; set; }  //this could be replaced when NameField issue is solved.
        public NameField PreferredBranchName { get; set; }   //Reference to NameField class
        public short BaseCurrencyId { get; set; }
        public short TimezoneId { get; set; }
    }

    public class BranchAddModelValidator : AbstractValidator<BranchAddModel>
    {
        public BranchAddModelValidator()
        {
            //trying to avoid writing this validation.
            RuleFor(x => x.BranchName)
                .NotEmpty()
                .Length(0, 128);

            RuleFor(x => x.ServiceTypeId)
                .NotEmpty();

            RuleFor(x => x.BaseCurrencyId)
                .NotEmpty();

            RuleFor(x => x.TimezoneId)
                .NotEmpty();
        }
    }
}

注意:如果您认为问题不清楚,请告诉我。

【问题讨论】:

  • 使用反射构建表达式树以传递给RuleFor
  • @Rob 你能举个例子吗?

标签: c# .net refactoring dry fluentvalidation


【解决方案1】:

我会尝试使用泛型。通过这种方式,您可以轻松地将其添加到其他模型和属性(CountryName、StateName)。

public class BranchAddModelValidator : AbstractValidator<BranchAddModel>
{
    public BranchAddModelValidator()
    {
        this.AddDefaultNameValidation(x => x.BranchName);

        RuleFor(x => x.ServiceTypeId)
            .NotEmpty();

        RuleFor(x => x.BaseCurrencyId)
            .NotEmpty();

        RuleFor(x => x.TimezoneId)
            .NotEmpty();
    }
}

public static class AbstractValidatorExtensions
{
    public static void AddDefaultNameValidation<T>(this AbstractValidator<T> validator, Expression<Func<T, string>> property)
    {
        validator.RuleFor(property)
            .NotEmpty()
            .Length(0, 128);
    }
}

注意:它可以编译,但我没有测试验证是否真的有效。 Fluent Validation 包对我来说是新的,我现在没有时间研究它,但看起来值得记住。

【讨论】:

    【解决方案2】:

    您可以执行以下操作,而不是包装类:

    var param = Expression.Parameter(typeof(BranchAddModel));
    var items = typeof(BranchAddModel).GetProperties()
        .Where(p => p.PropertyType == typeof(string))
        .Select(r => Expression.Lambda<Func<BranchAddModel, string>>(Expression.PropertyOrField(param, r.Name), param));
    
    foreach (var item in items)
    {
        RuleFor(item)
            .NotEmpty()
            .Length(0, 128);
    }
    

    这将构建一个可枚举的Expression&lt;Func&lt;BranchAddModel, string&gt;&gt;,然后您可以循环并传递给RuleFor

    【讨论】:

      猜你喜欢
      • 2018-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-09
      • 1970-01-01
      相关资源
      最近更新 更多