【问题标题】:MetadataType problem元数据类型问题
【发布时间】:2010-12-24 16:44:13
【问题描述】:

我正在使用 VS2008 SP1,WCF Ria 服务 2009 年 7 月 CTP。我发现 MetadataType 在部分类模式下不起作用,真的不知道我错过了什么:

工作:-

public partial class Person
{
    private string _Name;

    [Required(AllowEmptyStrings=false, ErrorMessage="Name required entry")]
    [StringLength(3)]
    public string Name
    {
        set{_Name = value;}
        get{return _Name;}
    }
}

class Program
{
    static void Main(string[] args)
    {
        Person p = new Person { Name="123432" };
        List res = new List();
        Validator.TryValidateObject(p,new ValidationContext(p,null,null),
            res,true);
        if (res.Count > 0)
        {
            Console.WriteLine(res[0].ErrorMessage);
            Console.ReadLine();
        }
    }
}

不工作

public partial class Person
{
    private string _Name;

    public string Name
    {
        set{_Name = value;}
        get{return _Name;}
    }
}

[MetadataType(typeof(PersonMetadata))]
public partial class Person
{
}


public partial class PersonMetadata
{
    [Required(AllowEmptyStrings=false, ErrorMessage="Name required entry")]
    [StringLength(3)]
    public string Name;
}

class Program
{
    static void Main(string[] args)
    {
        Person p = new Person { Name="123432" };
        List res = new List();
        Validator.TryValidateObject(p,new ValidationContext(p,null,null),
            res,true);
        if (res.Count > 0)
        {
            Console.WriteLine(res[0].ErrorMessage);
            Console.ReadLine();
        }
    }
}

【问题讨论】:

  • 在添加对 System.ComponentModel.DataAnnotations 命名空间的引用之前,我似乎遇到了这个问题。

标签: .net data-annotations


【解决方案1】:

编辑:我在这里找到了答案:http://forums.silverlight.net/forums/p/149264/377212.aspx

验证前,需要手动注册元数据类:

TypeDescriptor.AddProviderTransparent(
            new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Person), typeof(PersonMetadata)), typeof(Person));

        List<ValidationResult> res = new List<ValidationResult>();
        bool valid = Validator.TryValidateObject(p, new ValidationContext(p, null, null), res, true);

(原答案如下)

问题不在于您的部分类,而是 Validator.TryValidateObject 似乎无法识别 MetaDataType 属性。我有同样的问题 - MVC 2 中的内置验证识别元数据类,但 TryValidateObject 没有。

查看这些: Validating DataAnnotations with Validator class Validation does not work when I use Validator.TryValidateObject

顺便说一句,我不知道是否有必要,但我看到的所有元数据类示例都在每个属性上使用默认的 get/set:

[Required(AllowEmptyStrings=false, ErrorMessage="Name required entry")]
[StringLength(3)]
public string Name { get; set; }

【讨论】:

  • 也许我遗漏了什么,但 .AddProviderTransparent 似乎没有被定义。
  • 啊。看起来这是 4.0 特有的。
【解决方案2】:

非常感谢 Jeremy Gruenwald 的上述回答......我完全被这个问题所困扰。

我想基于这个解决方案创建一个标准的验证类,但我不想传入元数据类类型,因为它感觉很丑。

为了实现这一点,我创建了一个静态类,它对自定义属性进行查找以获取元数据类类型,然后在返回验证结果之前注册该类。

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

namespace MyApp.Validation
{
    public static class EntityValidator
    {
        public static List<ValidationResult> Validate(object instance, bool validateAllProperties = true)
        {
            RegisterMetadataClass(instance);

            var validationContext = new ValidationContext(instance, null, null);
            var validationResults = new List<ValidationResult>();

            Validator.TryValidateObject(instance, validationContext, validationResults, validateAllProperties);

            return validationResults;
        }

        private static void RegisterMetadataClass(object instance)
        {
            var modelType = instance.GetType();
            var metadataType = GetMetadataType(modelType);

            if (metadataType != null) 
            {
                TypeDescriptor.AddProviderTransparent(new AssociatedMetadataTypeTypeDescriptionProvider(modelType, metadataType), modelType);
            }
        }

        private static Type GetMetadataType(Type type)
        {
            var attribute = (MetadataTypeAttribute)type.GetCustomAttributes(typeof (MetadataTypeAttribute), true).FirstOrDefault();
            return attribute == null ? null : attribute.MetadataClassType;
        }
    }
}

用法很简单:

var errors = EntityValidator.Validate(myEntity);

【讨论】:

    【解决方案3】:

    如果您正在使用 WPF 和 EF,这对我一直有效...

    [MetadataType(typeof(Department.Metadata))]
    public partial class Department : BaseModel
    {
        static Department()
        {
            TypeDescriptor.AddProvider(new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Department),typeof(Metadata)), typeof(Department));
        }
        private sealed class Metadata
        {
            [Required(AllowEmptyStrings = false, ErrorMessage = "Department Name is required.")]
            [StringLength(50, ErrorMessage = "Name must be between 3 and 50 characters.", MinimumLength = 3)]
            public string Name;
    
            [StringLength(250, ErrorMessage = "Name must be between 10 and 250 characters.", MinimumLength = 10)]
            public string Description;
        }
    }
    

    以及实现它的基类......

    public abstract class BaseModel : IDataErrorInfo
    {
        #region Validation
        string IDataErrorInfo.Error
        {
            get { return null; }
        }
        string IDataErrorInfo.this[string propertyName]
        {
            get
            {
                var propertyInfo = GetType().GetProperty(propertyName);
                var results = new List<ValidationResult>();
                var result = Validator.TryValidateProperty(propertyInfo.GetValue(this, null), new ValidationContext(this, null, null)
                {
                    MemberName = propertyName
                }, results);
    
                if (result) return string.Empty;
                var validationResult = results.First();
                return validationResult.ErrorMessage;
            }
        }
        #endregion
    }
    

    【讨论】:

      猜你喜欢
      • 2021-04-24
      • 2018-10-27
      • 2011-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-02
      • 2014-10-13
      相关资源
      最近更新 更多