简体   繁体   中英

How check whether class members are not null or empty

I have a class with only string members like this :

public class MyClass
{
    public string MyProp1 { get; set; }
    public string MyProp2 { get; set; }
}

I create an instance :

Var myClass = new MyClass();

Later in the code, I'd like to know if all the member (MyProp1 and MyProp2) are not null or empty. I know I can use a if of course but there is much more properties than 2 in my real code.

Is there a way to do this ?

Thanks,

Using a dictionary based store for your properties is probably the easiest way of doing this:

public class MyClass
{
    private IDictionary<String, String> _store;

    public MyClass()
    {
        _store = new Dictionary<String, String>();
    }

    public string MyProp1 { 
        get { return GetOrDefault("MyProp1"); }
        set { _store["MyProp1"] = value; }
    }
    public string MyProp2 { 
        get { return GetOrDefault("MyProp2"); }
        set { _store["MyProp2"] = value; }
    }

    public Boolean HasData()
    {
        return _store.Any(x => !String.IsNullOrWhiteSpace(x.Value));
    }

    public Boolean IsEmpty()
    {
        return _store.All(x => String.IsNullOrWhiteSpace(x.Value));
    }   

    private String GetOrDefault(String propertyName)
    {
        if (_store.ContainsKey(propertyName))
        {
            return _store[propertyName];
        }

        return String.Empty;
    }
}

Another method for doing this would be to compare it with a default instance:

public class MyClass
{
    public string MyProp1 { get; set; }
    public string MyProp2 { get; set; }

    public static readonly MyClass Empty = new MyClass();

    public Boolean HasData()
    {
        return !Empty.Equals(this);
    }

    public Boolean IsEmpty()
    {
        return Empty.Equals(this);
    }
}

You can try to use the reflect to check the properties. You should need confirm that all the properties are public, and the type is string. Here is the code.

    public static bool IsNullOrEmpty(MyClass prop)
    {
        bool result = true;

        PropertyInfo[] ps = prop.GetType().GetProperties();

        foreach (PropertyInfo pi in ps)
        {
            string value = pi.GetValue(prop, null).ToString();

            if (string.IsNullOrEmpty(value))
            {
                result = false;
                break;
            }
        }

        return result;
    }

To check if your class contains 'any' properties which are null:

System.Reflection.PropertyInfo[] properties = myClass.GetType().GetProperties
                         (BindingFlags.Public | BindingFlags.Instance);         

bool hasNullProperty = properties.Any(y => y.GetValue(x, null) == null);

You can always initialize your class like

public class MyClass
{
    public MyClass() {
        this.MyProp1 = this.MyProp2 = String.Empty;
    }

    public string MyProp1 { get; set; }
    public string MyProp2 { get; set; }
}

and, unless your programmatically assign a null value to it, the new MyClass() will always have String.Empty in their 2 properties...


from comment:

What I do in those cases is call a helper, for example: string name = myHelper.CheckNode(xmlNode); and in that helper I check if it's null, any other check, I can easily tweek the helper method and it will be available to all elements, and you can extend it to support not only strings but all other data types as well

So, imagine that you are reading nodes from your XML, you write them like:

string name = myHelper.CheckNode(node);

in your helper, you could have something like:

XmlNodeList datasourceNodes = rootNode.SelectNodes("dataSources/dataSource");
foreach (XmlNode datasourceNode in datasourceNodes)
{
    DataSource dataSource = new DataSource();
    dataSource.Name = myHelper.CheckAttr(datasourceNode.Attributes["name"]);
    dataSource.ODBC = myHelper.CheckNode(datasourceNode.SelectSingleNode("odbc"));

    // or a variant (Extension Method)
    dataSource.UID  = datasourceNode.CheckNode("user");
    dataSource.PWD  = datasourceNode.CheckAttr("password");

    ds.Add(dataSource);
}

your helper then could have a method like:

public static string CheckAttr(XmlAttribute attr) 
{
    return attr == null ? "" : attr.Value.Trim();
}
public static string CheckNode(XmlNode node) 
{
    return node == null ? "" : node.InnerText.Trim();
}

or for the variant (Extension Method)

public static string CheckAttr(this XmlNode, string attrName)
{
    return attrName[attrName] == null ? "" : attrName[attrName].Value.Trim();
}
public static string CheckNode(this XmlNode, string nodeName)
{
    return node.SelectSingleNode(nodeName) == null ? 
                 "" : 
                 node.SelectSingleNode(nodeName).InnerText.Trim();
}

If there are many properties in the class, one way of handling this is storing them in a collection, such as an array or a dictionary, instead of declaring each property as a separate member of the class.

Then you can access data in the dictionary by key, which is as easy as accessing a property of a class. And the advantage is that you can loop over the dictionary and check all the properties in a loop.

I would suggest creating a function in your class where you check String.IsNullOrEmpty(MyProp1) etc. for all your properties. This way you at least have gathered all the ckecking functionality in a single place. And you only have this place to modify whenever you add new properties.

By using Attribute Base programming you can achieve this. In this approach you will need to place attribute over the class member, and validation is can be done. You can also use Microsoft Enterprise Library for this.

To check if all the elements are set you could add a IsEmpty() method to your class that would check the internal properties. Then you wouldn't have to duplicate the if statements everywhere trough your code.

In your IsEmpty() method you can use a regular if statement to check all the fields or you can use reflection to automaticaly retrieve all string properties and check their values. The performance of reflection will be worse then a normal if check but if that's not a problem you can reuse the reflection code in all your entities to check their values.

Probably the best way would be to :

Restructure your properties in the form of a Dictionary of strings. Loop through the dictionary to test the strings using string.IsNullOrEmpty(). You could replace the N getter/setters by a single Indexer property which sets and retrieves the strings directly from the dictionary based on a key

You can use try the following style. I haven't tried it before but you might see if it helps

If (String.IsNullOrEmpty(string1 && string2 && string3)) 

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