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

How do I check if an anonymous object properties are not empty C#

我有一个 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,它将 return 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

调试时我注意到:

我强烈建议为此使用命名的 class 而不是匿名的。显然,您对 xml 中的实例公开的属性有一些深入的了解,因此隐藏这些知识是没有用的。

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

我想你想做的不仅仅是验证你的对象。你肯定想和他们点什么。为此,您需要知道它们公开了哪些成员。在您当前的实施中,它们只是 objects,不会向其客户公开太多内容。所以为了做任何事情你需要这样的东西:

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

但是您丢失了有关 theType 实际是什么的所有信息,因此您对该对象所能做的就是调用 ToStringEquals 和一些其他派生自 object.

在您的特殊情况下,您已经知道 xml 中的实例有一个 StudentName- 和一个 studentId-属性。那你为什么要把它扔掉,假装你不知道呢?

截至 MSDN

To pass an anonymous type, or a collection that contains anonymous types, as an argument to a method, you can declare the parameter as type object. However, doing this defeats the purpose of strong typing. If you must store query results or pass them outside the method boundary, consider using an ordinary named struct or class instead of an anonymous type.

我是这样解决的:

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

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

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

如果您知道自己的 Xml-Structur,为什么要丢失该信息。