如何检查匿名对象属性是否为空C#

时间:2017-12-14 12:47:54

标签: c# xml anonymous-types

我有一个WebApi,它有一些接受XMLDocument值的动作方法。在这些函数中,我将XML转换为AnonymousObject,然后,我做了我的逻辑。

现在,我得到了带有空属性的XML,我需要做一个检查,可以检查该匿名对象中的所有属性,如果它们为null或为空,我做了一些但是它没有用,但是,我传递了一个带有空属性的XML。

<Students>
    <Student ID="" Name="" />
    <Student ID="" Name="" />
</Students>

这是我得到的XML输入的一个示例,并且还有其他一些形式,因此,我编写了一个函数,在将XML反序列化为匿名对象后,检查属性是否为空,如下所示:

//This handles the conversion from XML to the anonymous object

XDocument doc;
using (var sr = new StringReader(request.InnerXml))
{
    doc = XDocument.Load(sr);
}

var clientList = doc.Descendants()
    .Where(d => string.Equals(d.Name.LocalName, "Student", StringComparison.OrdinalIgnoreCase))
    .Select(
        d =>
            new
            {
                studentId = d.Attributes().SingleOrDefault(a =>
                        string.Equals(a.Name.LocalName, "ID", StringComparison.OrdinalIgnoreCase))
                    ?.Value,
                studentName = d.Attributes().SingleOrDefault(a =>
                        string.Equals(a.Name.LocalName, "Name", StringComparison.OrdinalIgnoreCase))
                    ?.Value
            }).ToList();

然后我编写了该函数,它应该验证匿名对象的属性,都应该有一个值,但是如果我传递了上面的XML,它将返回 FALSE ,好像没有空值的属性:

public static bool IsAnyNullOrEmpty(object objectToBeChecked)
{
    try
    {
        foreach (PropertyInfo pi in objectToBeChecked.GetType().GetProperties())
        {
            if (pi.PropertyType == typeof(string))
            {
                string value = (string)pi.GetValue(objectToBeChecked);
                if (string.IsNullOrEmpty(value))
                {
                    return true;
                }
            }
        }
        return false;
        //return objectToBeChecked.GetType().GetProperties()
        //    .Where(pi => pi.GetValue(objectToBeChecked) is string)
        //    .Select(pi => (string) pi.GetValue(objectToBeChecked))
        //    .Any(string.IsNullOrEmpty);
    }
    catch (Exception ex)
    {
        return true;
    }
}

有什么建议吗?

编辑#1

调试时我注意到了:

  • 物业名称:<>f__AnonymousType3`1
  • 物业类型:Name = "<>f__AnonymousType3`1" FullName = "<>f__AnonymousType3`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"

3 个答案:

答案 0 :(得分:2)

我强烈建议使用命名类而不是匿名类。显然,您对xml中的实例所展示的属性有一定的了解,因此无需隐藏这些知识。

想象一下,有一天你不仅需要字符串属性,还需要数字。然后你必须重新发明你的逻辑的很大一部分,不仅仅是验证,而只是实际的工作与对象。

我想你想做的不仅仅是验证你的对象。你肯定想与他们一起。为了做到这一点,你需要知道他们揭露的成员。在您当前的实现中,它们只是objects,不会给客户带来太多暴露。所以为了做任何事你需要这样的东西:

var a = ((theType) myInstance).StudentName;

但是您已经丢失了有关theType实际上是什么的所有信息,因此您可以使用该对象调用ToStringEquals和其他一些来自{{1}的成员}}

在您的特殊情况下,您已经知道xml中的实例具有object - 和StudentName - 属性。那你为什么要把它丢掉呢?就好像你不知道那样?

截至MSDN

  

要将匿名类型或包含匿名类型的集合作为方法的参数传递,可以将参数声明为类型对象。但是,这样做会破坏强类型的目的。如果你必须   存储查询结果或将它们传递到方法边界之外,考虑一下   使用普通的命名结构或类而不是匿名类型。

答案 1 :(得分:2)

我解决了这个问题:

public static bool IsAnyNullOrEmpty(object objectToBeChecked, params string[] parametersToBeChecked)
{
    foreach (var obj in (IEnumerable)objectToBeChecked)
    {
        foreach (var pi in obj.GetType().GetProperties())
        {
            if (parametersToBeChecked.Contains(pi.Name))
            {
                var value = (string)pi.GetValue(obj);
                if (string.IsNullOrEmpty(value))
                {
                    return true;
                }
            }
        }
    }

    return false;
}

这将获取您要检查的对象(匿名对象)和属性名称,这对我有用。

答案 2 :(得分:1)

如果要在某个方法中传递对象,则需要使用具体的类实现。 复制xml结构,让Visual Studio为您创建反序列化类。 编辑 - &gt;选择性粘贴 - &gt;将Xml粘贴为Class

如果你知道你的Xml-Structur,为什么要放弃这些信息。