使用 PropertyDescriptor 确定属性是否为复杂对象

2024-03-27

我正在尝试在 WCF 服务中进行一些验证,为此我正在使用WCF数据注释 https://wcfdataannotations.codeplex.com/我发现通过这个帖子 http://www.devtrends.co.uk/blog/validating-wcf-service-operations-using-system.componentmodel.dataannotations

问题是它不会递归验证,因此对于嵌套对象它不起作用。我们来说说这个

[DataContract]
public class Model
{
    [DataMember]
    [Required(ErrorMessage = "RequiredOne is required")]
    public string RequiredOne { get; set; }

    [DataMember]
    [StringLength(10, ErrorMessage = "Not Required should be at most 10 characters long")]
    public string NotRequired { get; set; }

    [DataMember]
    [Required(ErrorMessage = "ChildModel is required")]
    public ChildModel ChildModel { get; set; }

}

[DataContract]
public class ChildModel
{
    [DataMember]
    [Required(ErrorMessage = "RequiredValue is required")]
    public string RequiredValue { get; set; } 

    [DataMember]
    public string NotRequiredValue { get; set; }

}

它不会得到所需的 childModelRequiredValue。

所以我正在研究该 dll 的源代码并尝试使其工作。实际的代码是

public class DataAnnotationsObjectValidator : IObjectValidator
{
    public IEnumerable<ValidationResult> Validate(object input)
    {
        if (input == null) return Enumerable.Empty<ValidationResult>();

        return from property in TypeDescriptor.GetProperties(input).Cast<PropertyDescriptor>()
               from attribute in property.Attributes.OfType<ValidationAttribute>()
               where !attribute.IsValid(property.GetValue(input))
               select new ValidationResult
               (
                   attribute.FormatErrorMessage(string.Empty),
                   new[] { property.Name }
               );
    }
} 

所以我的想法是把它改成这样

public IEnumerable<ValidationResult> Validate(object input)
{
    if (input == null) return Enumerable.Empty<ValidationResult>();

    var validationResults = new List<ValidationResult>();

    foreach (var prop in TypeDescriptor.GetProperties(input).Cast<PropertyDescriptor>())
    {
        foreach (var att in prop.Attributes.OfType<ValidationAttribute>())
        {
            //This doesn't work, it's one of the several 
            //attempts I've made
            if (prop.ComponentType.IsClass)
                Validate(prop.ComponentType);

            if (!att.IsValid(prop.GetValue(input)))
            {
                validationResults.Add(new ValidationResult(
                        att.FormatErrorMessage(string.Empty),
                        new[] { prop.Name }
                ));
            }
        }
    }

    return validationResults;
}

目的是检查是否有任何属性是复杂的,如果是这种情况,则递归地验证自身,但我不确定如何检查是否将“props”转换为 TypeDescriptor。

Thanks


在我看来,下面的代码应该可以解决问题:

public IEnumerable<ValidationResult> Validate(object input)
{
    return ValidateWithState(input, new HashSet<object>());
}

private IEnumerable<ValidationResult> ValidateWithState(object input, HashSet<object> traversedInputs)
{
    if (input == null || traversedInputs.Contains(input))
    {
       return Enumerable.Empty<ValidationResult>();
    }

    var validationResults = new List<ValidationResult>();

    foreach (var prop in TypeDescriptor.GetProperties(input).Cast<PropertyDescriptor>())
    {
        foreach (var att in prop.Attributes.OfType<ValidationAttribute>())
        {
            if (!att.IsValid(prop.GetValue(input)))
            {
                validationResults.Add(new ValidationResult(
                        att.FormatErrorMessage(string.Empty),
                        new[] { prop.Name }
            ));
        }

        traversedInputs.Add(input);

        if (prop.PropertyType.IsClass || prop.PropertyType.IsInterface))
        {
            validationResults.AddRange(ValidateWithState(prop.GetValue(input), traversedInputs));
        }
    }

    return validationResults;
}

可能不是最优雅的解决方案,但我认为它会起作用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 PropertyDescriptor 确定属性是否为复杂对象 的相关文章

  • 如何使用 MVVM 更新 WPF 中编辑的数据? [复制]

    这个问题在这里已经有答案了 我正在为聊天应用程序构建 UI 设计 在尝试更新所选联系人的消息时遇到问题 选择现有联系人 选择编辑选项 然后编辑其属性 例如用户名和图像 后 唯一进行的更改是联系人的用户名和图像 我仍然想更改 MessageM
  • 键盘加速器在 UWP 应用中停止工作

    我正在尝试将键盘加速器添加到 UWP 应用程序中的 CommandBar 菜单项 当应用程序启动时 这工作正常 但在我第一次打开溢出菜单后 加速器停止工作 这似乎不会发生在主要命令 菜单之外 上 只有溢出菜单内的辅助命令才会发生 此外 单击
  • 如何在不实例化一个类的情况下检查它是否继承了另一个类? [复制]

    这个问题在这里已经有答案了 假设我有一个如下所示的类 class Derived some inheritance stuff here 我想在我的代码中检查类似的内容 Derived is SomeType 但看起来像is运算符需要 De
  • 从 future 中检索值时的 SIGABRT

    我在使用 C 11 future 时遇到问题 当我打电话时wait or get 关于返回的未来std async 程序接收从mutex标头 可能是什么问题呢 如何修复它 我在 Linux 上使用 g 4 6 将以下代码粘贴到 ideone
  • 如何在编译C代码时禁用警告?

    我正在使用 32 位 Fedora 14 系统 我正在使用编译我的源代码gcc 有谁知道如何在编译c代码时禁用警告 EDIT 是的 我知道 最好的办法是修复这些警告以避免任何未定义 未知的行为 但目前在这里 我第一次编写了巨大的代码 并且在
  • 如何使用 wpf webbrowser 将数据发布到 Web 服务器

    我想从数据库获取数据并使用它来让用户登录到网站 我有一个包含 Web 浏览器控件的 wpf 页面 我有这样的代码 用于将用户登录到用 php 编写的网站
  • 在 MATLAB 中创建共享库

    一位研究人员在 MATLAB 中创建了一个小型仿真 我们希望其他人也能使用它 我的计划是进行模拟 清理一些东西并将其变成一组函数 然后我打算将其编译成C库并使用SWIG https en wikipedia org wiki SWIG创建一
  • 手动将 ClientBase 集合类型从 Array[] 更改为 List<>

    我将自己的 WCF 代理与 Client Base 一起使用 我想做一些类似于 svc util 中的 ct 属性的操作 并告诉代理返回 List 集合类型 我不能使用 List 因为实体由 nhibernate 管理 所以我必须使用 IL
  • 操纵 setter 以避免 null

    通常我们有 public string code get set 如果最终有人将代码设置为 null 我需要避免空引用异常 我尝试这个想法 有什么帮助吗 public string code get set if code null cod
  • 如何添加重试以调用 Web 服务?

    我有一个应用程序调用使用 wsHttpBinding 的 Web 服务 我需要在连接超时等情况下对 Web 服务调用实现某种重试功能 执行此操作的最佳方法是什么 我已经阅读过有关 WS ReliableMessaging 的内容 但这不是
  • 格式化货币

    在下面的示例中 逗号是小数点分隔符 我有这个 125456 89 我想要这个 125 456 89 其他示例 23456789 89 gt 23 456 789 89 Thanks 看看这个例子 double value 12345 678
  • 以编程方式更新 ClickOnce 应用程序的部署清单会导致缺少 4.0 中所需的 <兼容框架> 元素

    我正在致力于自动化 NET 4 0 ClickOnce WPF 应用程序的安装程序 该应用程序需要在应用程序配置文件 我经历了寻找必须遵循的具体步骤的棘手过程Mage exe http msdn microsoft com en us li
  • C#中Enum中定义的value__是什么

    What value 可能在这里 value MSN ICQ YahooChat GoogleTalk 我运行的代码很简单 namespace EnumReflection enum Messengers MSN ICQ YahooChat
  • 从事务范围调用 WCF 服务方法

    我有这样的代码 using TransactionScope scope TransactionScopeFactory CreateTransactionScope some methodes calls for which scope
  • 使用(linq to sql)更新错误

    我有两个表 通过外键 CarrierID 绑定 Carrier CarrierID CarrierName CarrierID 1 CarrierName DHL CarrierID 2 CarrierName Fedex Vendor V
  • #pragma pack(16) 和 #pragma pack(8) 的效果总是相同吗?

    我正在尝试使用来对齐数据成员 pragma pack n http msdn microsoft com en us library 2e70t5y1 28v vs 100 29 aspx 以下面为例 include
  • 纯虚函数可能没有内联定义。为什么?

    纯虚函数是那些虚函数并且具有纯说明符 0 第 10 4 条第 2 款C 03 的内容告诉我们什么是抽象类 顺便说一句 如下 注意 函数声明不能 同时提供纯说明符和定义 尾注 示例 struct C virtual void f 0 ill
  • 使用 Chrome 和 Selenium 设置 LocalStorage

    我正在尝试使用 OpenQA Selenium 和 Chrome 设置本地存储键和值 我认为这相当微不足道 但我似乎无法让它发挥作用 我对 C 很陌生 所以我可能错过了一些东西 无论如何 我有这个功能 public static void
  • 从有符号字符转换为无符号字符然后再转换回来?

    我正在使用 JNI 并有一个 jbyte 类型的数组 其中 jbyte 表示为有符号字符 即范围从 128 到 127 jbyte 表示图像像素 对于图像处理 我们通常希望像素分量的范围为0到255 因此 我想将jbyte值转换为0到255
  • 无法使 Polly 超时策略覆盖 HttpClient 默认超时

    我正在使用 Polly 重试策略 并且正如预期的那样 在重试过程中HttpClient达到 100 秒超时 我尝试了几种不同的方法来合并 Polly 超时策略 将超时移至每次重试而不是总计 但 100 秒超时仍然会触发 我读过大约 5 个

随机推荐