如何从 DataAnnotations 获取 StringLength

How to get the StringLength from DataAnnotations

更新建议后我仍然收到错误

都尝试了 .SingleOrDefault()FirstOrDefault()

我需要检索 StringLength 注释值,这是我的代码,但出现以下错误。

我试图实现与 here 几乎相同的代码,但出现错误:

Sequence contains no elements

    public static class DataAnnotation
    {
        public static int GetMaxLengthFromStringLengthAttribute(Type modelClass, string propertyName)
        {
            int maxLength = 0;
            var attribute = modelClass.GetProperties()
                            .Where(p => p.Name == propertyName)
                            .Single()
                            .GetCustomAttributes(typeof(StringLengthAttribute), true)
                            .Single() as StringLengthAttribute;

            if (attribute != null)
                maxLength = attribute.MaximumLength;

            return 0;
        }
    }

//呼叫:

int length = DataAnnotation.GetMaxLengthFromStringLengthAttribute(typeof(EmployeeViewModel), "Name");


public class EmployeeViewModel
{         
    [StringLength(20, ErrorMessage = "Name cannot be longer than 20 characters.")] 
    public string Name{ get; set; }
}

你可以从When you get theLINQ Error “Sequence contains no elements”, this is usually because you are using the First() or Single() command rather than FirstOrDefault() and SingleOrDefault()那里得到答案。

所以你需要尝试使用 SingleOrDefault() 而不是像

这样的 Single()
var attribute = modelClass.GetProperties()
                            .Where(p => p.Name == propertyName)
                            .SingleOrDefault()
                            .GetCustomAttributes(typeof(StringLengthAttribute), true)
                            .SingleOrDefault() as StringLengthAttribute;

您是否尝试将长度显示为错误消息的一部分?如果是这样,我相信你可以把...

public class EmployeeViewModel
{         
    [StringLength(20, ErrorMessage = "{0} cannot be longer than {1} characters.")] 
    public string Name{ get; set; }
}

我能够弄清楚,经过测试并且效果很好,以防其他人在看!

  StringLengthAttribute strLenAttr = typeof(EmployeeViewModel).GetProperty(name).GetCustomAttributes(typeof(StringLengthAttribute), false).Cast<StringLengthAttribute>().SingleOrDefault();
  if (strLenAttr != null)
  {
     int maxLen = strLenAttr.MaximumLength;
  }
var maxLength = typeof(EmployeeViewModel)
                    .GetProperty("Name")
                    .GetCustomAttributes<StringLengthAttribute>()
                    .FirstOrDefault()
                    .MaximumLength;

因为我只是在处理这个问题,所以我想我应该提供我正在使用的 LinqPad 代码。在 Linqpad 中 运行 已经足够完整,如果您想探索,只需添加导入即可。

请注意我在哪里评论您实际需要的部分。我发现有时在没有上下文的情况下改编代码很棘手。

///The rest of the code given as context as I'm working on a T4 template to create Model classes from Datalayer classes, so the iteration is required in my case
void Main()
{
    CVH p = new CVH();
    Type t = p.GetType();

    foreach (PropertyInfo prop in t.GetProperties()) //Iterating through properties
    {
        foreach (var facet in prop.GetCustomAttributes()) //Yank out attributes
        {
        //The bit you need
            if ((Type)facet.TypeId == typeof(StringLengthAttribute)) //What type of attribute is this? 
            {
                StringLengthAttribute _len = (StringLengthAttribute)facet; //Cast it to grab Maximum/MinimumLengths etc.
                Console.WriteLine($"My maximum field length is { _len.MaximumLength}");
                //End of the bit you need
                Console.WriteLine(_len.MinimumLength);              
            }
        }
    }
}
///Test class with some attributes
public class CVH
{
    [StringLength(50)]
    [DataType(DataType.PhoneNumber)]
    public string phone_1 { get; set; }
    [Required(ErrorMessage = "id is required")]
    public int id { get; set; }
    [Required(ErrorMessage = "id is required")]
    public int contact_id { get; set; }
}