Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
210 views
in Technique[技术] by (71.8m points)

c# - Is it possible to use DataAnnotations with Interfaces?

I want to use DataAnnotations to validate classes that implements some interfaces, and so I'm adding validation attributes to the interface, like this:

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

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

It doesn't work when I try to use Validator.TryValidateObject.

Is there any way to make this instead of having to write a custom TryValidateObject method?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I'm surprised no one mentioned MetadataTypeAttribute. But yes, this works.

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


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

As for using an Interface directly (using Customer: ICustomerMetaData):

The product team does not want to implement this feature, for two main reasons:

? Consistency with DataAnnotations.Validator

? Consistency with validation behavior in ASP.Net MVC

? Tricky scenario: a class implements two interfaces that have the same property, but with conflicting attributes on them. Which attribute would take precedence?

While MVC automatically registers the MetaData with the TypeDescriptor, you may have to manually add it yourself:

  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; }
     }
  }

Output:

is Valid = False

is Valid = True


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...