简体   繁体   中英

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

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.

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.

<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:

//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:

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
  • Property Type: Name = "<>f__AnonymousType3`1" FullName = "<>f__AnonymousType3`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"

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.

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.

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:

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 .

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?

As of 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.

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.

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM