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

时间:2021-04-17 19:26:52

I have a WebApi which has some action methods that accepts an XMLDocument value. Inside these functions I converted that XML to AnonymousObject, then, I do my logic.

我有一个WebApi,它有一些接受XMLDocument值的操作方法。在这些函数中,我将XML转换为signatousobject,然后进行逻辑运算。

Now, I got the XML with empty attributes, and I need to do a check which can check all properties in that anonymous object if which are null or empty, I did something there but it didn't work, although, I passed an XML with empty attributes.

现在,我得到了具有空属性的XML,我需要做一个检查,如果匿名对象中的所有属性为空或空,我在那里做了一些事情,但它不起作用,尽管我传递了一个具有空属性的XML。

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

This was an example of XML inputs which I got, and there are some other forms for the same, so, I wrote a function that checks if the attributes are empty or not after deserializing the XML to an anonymous object as follows:

这是我得到的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();

Then I wrote that function which should validate that anonymous object's properties, all should have a value, but if I passed the above XML, it will return FALSE as if there is no property with empty value:

然后我编写了一个函数,该函数应该验证匿名对象的属性,所有这些都应该有一个值,但是如果我传递了上面的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;
    }
}

Any advice?

任何建议吗?

EDIT #1

While debugging I noticed that:

调试时我注意到:

  • Property Name: <>f__AnonymousType3`1
  • 属性名:< > f__AnonymousType3”1
  • Property Type: Name = "<>f__AnonymousType3`1" FullName = "<>f__AnonymousType3`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"
  • 属性类型:Name = "<> f__accounoustype3 ' 1" FullName = "<> f__oustype3 ' 1"[系统]。String, mscorlib, Version=4.0.0.0, Culture=中性,PublicKeyToken=b77a5c561934e089]

3 个解决方案

#1


2  

I strongly suggest to use a named class instead of an anonymous one for that. Obviously you have some strong knowledge on what properties the instances in the xml expose, so there´s no use on hiding this knowledge away.

我强烈建议使用命名类而不是匿名类。显然你有强大的知识属性的实例xml暴露,所以没有使用´s隐藏这些知识。

Imagine some day you don´t want only string-properties but also numbers. Then you´d have to re-invent great parts ofyour logic, not only the validation but only the actual work with the objects.

´想象有一天你不希望只字符串属性,而且数字。然后你´d要重新发明伟大的逻辑部分,不仅验证对象的实际工作。

I suppose you want to do more than just validating your objects. You surely want to do something with them. In order to do so you need to know what members they expose. In your current implementation they´re just objects, which don´t expose much to their clients. So in order to do anything you´d need something like this:

我想你想做的不仅仅是验证你的对象。你肯定想用它们做点什么。为了做到这一点,您需要知道他们公开了哪些成员。在当前实现他们´re对象,´,不暴露他们的客户。为了你做任何事´d需要是这样的:

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

But you´ve lost all information about what theType actually is, so all you can do with the object is calling ToString, Equals and some other members derived from object.

但是你´已经失去了所有信息所有实际上是什么,所以你能做的对象调用ToString,等于和一些来自其他成员对象。

In your special case you allready know that the instance in your xml has a StudentName- and a studentId-property. So why should you throw that away and do as if you didn´t know that?

在特殊情况下,您都知道xml中的实例有一个StudentName和一个studentied属性。所以你为什么要扔掉,,如果你根本´t知道吗?

As of MSDN:

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.

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

#2


1  

I solved it like that:

我是这样解的

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

This will take the object (anonymous object) and properties names which you want to check, this works for me.

这将获取您想要检查的对象(匿名对象)和属性名称,这对我来说是可行的。

#3


1  

you need to use a concrete class implementation if you want to pass your object in some method. Copy your xml structur and let Visual Studio create a deserialization class for you. Edit -> Paste Special -> Paste Xml as Class

如果您想在某个方法中传递对象,需要使用具体的类实现。复制xml structur并让Visual Studio为您创建反序列化类。编辑->粘贴特殊->将Xml作为类粘贴

If you know your Xml-Structur, why you want to loose that information.

如果您知道Xml-Structur,为什么要释放这些信息。

#1


2  

I strongly suggest to use a named class instead of an anonymous one for that. Obviously you have some strong knowledge on what properties the instances in the xml expose, so there´s no use on hiding this knowledge away.

我强烈建议使用命名类而不是匿名类。显然你有强大的知识属性的实例xml暴露,所以没有使用´s隐藏这些知识。

Imagine some day you don´t want only string-properties but also numbers. Then you´d have to re-invent great parts ofyour logic, not only the validation but only the actual work with the objects.

´想象有一天你不希望只字符串属性,而且数字。然后你´d要重新发明伟大的逻辑部分,不仅验证对象的实际工作。

I suppose you want to do more than just validating your objects. You surely want to do something with them. In order to do so you need to know what members they expose. In your current implementation they´re just objects, which don´t expose much to their clients. So in order to do anything you´d need something like this:

我想你想做的不仅仅是验证你的对象。你肯定想用它们做点什么。为了做到这一点,您需要知道他们公开了哪些成员。在当前实现他们´re对象,´,不暴露他们的客户。为了你做任何事´d需要是这样的:

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

But you´ve lost all information about what theType actually is, so all you can do with the object is calling ToString, Equals and some other members derived from object.

但是你´已经失去了所有信息所有实际上是什么,所以你能做的对象调用ToString,等于和一些来自其他成员对象。

In your special case you allready know that the instance in your xml has a StudentName- and a studentId-property. So why should you throw that away and do as if you didn´t know that?

在特殊情况下,您都知道xml中的实例有一个StudentName和一个studentied属性。所以你为什么要扔掉,,如果你根本´t知道吗?

As of MSDN:

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.

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

#2


1  

I solved it like that:

我是这样解的

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

This will take the object (anonymous object) and properties names which you want to check, this works for me.

这将获取您想要检查的对象(匿名对象)和属性名称,这对我来说是可行的。

#3


1  

you need to use a concrete class implementation if you want to pass your object in some method. Copy your xml structur and let Visual Studio create a deserialization class for you. Edit -> Paste Special -> Paste Xml as Class

如果您想在某个方法中传递对象,需要使用具体的类实现。复制xml structur并让Visual Studio为您创建反序列化类。编辑->粘贴特殊->将Xml作为类粘贴

If you know your Xml-Structur, why you want to loose that information.

如果您知道Xml-Structur,为什么要释放这些信息。