Подтвердить что ты не робот

Можно ли использовать DataAnnotations с интерфейсами?

Я хочу использовать DataAnnotations для проверки классов, которые реализуют некоторые интерфейсы, и поэтому я добавляю атрибуты проверки для интерфейса, например:

public interface IUser
{
    [Required]
    string Name { get; set; }

    [Display(Name = "Email Address")]
    [Required]
    string Email { get; set; }
}

Это не работает, когда я пытаюсь использовать Validator.TryValidateObject.

Есть ли способ сделать это вместо того, чтобы писать пользовательский метод TryValidateObject?

4b9b3361

Ответ 1

Я удивлен, что никто не упомянул MetadataTypeAttribute. Но да, это работает.

[MetadataType(typeof(ICustomerMetaData))]
public partial class Customer
{
}


public interface ICustomerMetaData
{
  // Apply RequiredAttribute
  [Required(ErrorMessage = "Title is required.")]
  string Title { get; }
}

Что касается непосредственного использования интерфейса (используя Customer: ICustomerMetaData):

Команда разработчиков не хочет реализовывать эту функцию по двум основным причинам:

• Согласованность с DataAnnotations.Validator

• Согласованность с проверочным поведением в ASP.Net MVC

• Сложный сценарий: класс реализует два интерфейса, которые имеют одно и то же свойство, но с конфликтующими атрибутами. Какой атрибут будет иметь приоритет?

Хотя MVC автоматически регистрирует метаданные с помощью TypeDescriptor, вам, возможно, придется добавить их вручную:

  using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.ComponentModel.DataAnnotations;

  public class Program
  {
     public static void Main()
     {
        var customer = new Customer();

        TypeDescriptor.AddProviderTransparent(
          new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Customer), 
            typeof(ICustomerMetaData)), 
            typeof(Customer));

        var context = new ValidationContext(customer);
        var validationResults = new List<ValidationResult>();

        var isValid = Validator.TryValidateObject(
          customer, context, validationResults, true);
        Console.WriteLine($"is Valid = {isValid}");

        customer.Title = "I has Title";

        isValid = Validator.TryValidateObject(
          customer, context, validationResults, true);
        Console.WriteLine($"is Valid = {isValid}");


        Console.ReadKey();
     }

     [MetadataType(typeof(ICustomerMetaData))]
     public partial class Customer
     {
        public string Title { get; set;  }
     }

     public interface ICustomerMetaData
     {
        // Apply RequiredAttribute
        [Required(ErrorMessage = "Title is required.")]
        string Title { get; }
     }
  }

Выход:

Действительный = Ложный

Действительный = Истинный

Ответ 2

Если вы используете базовый класс вместо интерфейса, атрибуты будут работать нормально.