2

I've been looking and found this which describes to return a bool if value is null. The code, I'm using is from this snippet Client client = new Client{ FirstName = "James"};

client.GetType().GetProperties()
.Where(pi => pi.GetValue(client) is string)
.Select(pi => (string) pi.GetValue(client))
.Any(value => string.IsNullOrEmpty(value));

But instead of returning if the value is null or not (the bool) I would like to retrieve all the properties values where they are not null.

I've tried making changes to the code, but unsuccessful.

Many thanks

EDIT

public class Client
{
   public string FirstName { get; set; }
   public string LastName { get; set; }
   //...
}

Client client = new Client();
client.FirstName = "James";
client.LastName = "";

Using my 'Client' class, I would like to iterate over all the properties within my class, and where the value isn't null or empty string, I would return the value, in this example, I would only return a string "James".

Hope that makes sense.

James
  • 1,363
  • 19
  • 28
  • Shouldn't it be like this: `value => !string.IsNullOrEmpty(value)` – FaizanHussainRabbani Mar 07 '18 at 10:37
  • Can you print to console only the properties? without any filtering of them? – Dina Bogdan Mar 07 '18 at 10:39
  • Hi Faizan. This will still return a bool, what I'm looking for is the actual value, so if I have a property 'Name' and someone answers 'James', the code above will show me if this is true or not, because it's been answered, but I would like the actual value of the answer 'James'. Hope this makes sense – James Mar 07 '18 at 10:41
  • 3
    _"instead of returning [...] the bool [...] I would like to retrieve all the properties values"_ - so, change `Any()` to `Where()`? – CodeCaster Mar 07 '18 at 10:41
  • Hi CodeCaster, I did try that before, no results get returned – James Mar 07 '18 at 10:46
  • It would be awesome if you could provide a [mcve] with a sample class and values, and expected values based on that sample. – mjwills Mar 07 '18 at 10:46
  • Hi @mjwills. You're absolutely correct, apologises. Hopefully my edit makes more sense now – James Mar 07 '18 at 10:54
  • `pi.GetValue(myObject) is string` is unneccessary, you can check the type directly. – Manfred Radlwimmer Mar 07 '18 at 10:54
  • @James: Your question should include the code you tried that did not work, not the code that does something different and you used as a starting point. We have no idea why your code didn't work because you didn't include it... – Chris Mar 07 '18 at 10:58
  • 1
    @James *why* do you want to do that? Do you want to serialize them, convert them to JSON, or store them in a database? You can do all these *without* using reflection. For example, JSON.NET can skip null properties if you change the default `NullValueHandling` property, eg `new JsonSerializer { NullValueHandling = NullValueHandling.Ignore};` – Panagiotis Kanavos Mar 07 '18 at 11:01

3 Answers3

5

There are some issues:

return myObject.GetType().GetProperties()
.Where(pi => pi.GetValue(myObject) is string) // this wastes time getting the value
.Select(pi => (string) pi.GetValue(myObject))
.Any(value => string.IsNullOrEmpty(value)); //  Any will return a bool

So change this to:

return myObject.GetType().GetProperties()
.Where(pi => pi.PropertyType == typeof(string)) // check type
.Select(pi => (string)pi.GetValue(myObject)) // get the values
.Where(value => !string.IsNullOrEmpty(value)); // filter the result (note the !)

Also, ensure that your properties are properties and not fields.

Steve Harris
  • 5,014
  • 1
  • 10
  • 25
3

Use Where instead of Any. Also you were missing an ! at !string.IsNullOrEmpty(value).

I modified your code to return a dictionary with property values indexed by name.

var stringPropertyValuesByName = client.GetType().GetProperties()
    .Where(pi => pi.PropertyType == typeof(string)) // use type check as Steve Harris suggested 
    .Select(pi => new { Val = (string) pi.GetValue(client), Name = pi.Name })
    .Where(pi => !string.IsNullOrEmpty(pi.Val))
    .ToDictionary(pi => pi.Name, pi => pi.Val);

C# Fiddle

Georg Patscheider
  • 9,357
  • 1
  • 26
  • 36
2

If you want to get all not null properties that are also not empty strings i suggest:

using System;
using System.Linq;

class Cls
{
    public string Prop1 {get; set;}

    public object Prop2 {get; set;}

    public int Prop3 {get; set;}

    public string Prop4 {get; set;}

}

public class Program
{
    public static void Main()
    {
        var obj = new Cls() { Prop1 = "abc", Prop3 = 5 };

        var props = obj
            .GetType()
            .GetProperties()
            .Select(p => p.GetValue(obj))
            .Where(x => x != null || ( x is string && (string)x != ""))
            .ToList();

        Console.WriteLine(string.Join(",", props));
    }
}

produces:

abc,5

thehennyy
  • 4,020
  • 1
  • 22
  • 31