6

I have a number (maybe a lot) of classes that are simple like so

 public class ResultA
    {
        public DateTime Date { get; set; }
        public int Year { get; set; }
        public int Month { get; set; }
        public int Day { get; set; }
    }

 public class ResultB
    {
        public string Number { get; set; }
        public int Count { get; set; }
        public string Update { get; set; }
        public int Jewels{ get; set; }
    }

There is no common interface, but they don't have methods simply properties.

I would like to be able to convert any type like this into a KeyValuePair<string,string> with the property name and the value if it is set.

Is there anyway of doing this horrible thing!?

Loofer
  • 6,841
  • 9
  • 61
  • 102
  • 4
    Sounds like Reflection is your only way. – Patrik Jun 10 '15 at 11:44
  • Does this answer your question? [How to convert object to Dictionary in C#?](https://stackoverflow.com/questions/11576886/how-to-convert-object-to-dictionarytkey-tvalue-in-c) – Jim G. Apr 28 '22 at 17:01

2 Answers2

19

Peter beat me to it, but here is a quick linqpad:

void Main()
{
    GetValues(new ResultA
    {
        Date = DateTime.Now,
        Year = 2000
    }).Dump();
}

public IDictionary<string, string> GetValues(object obj) 
{
    return obj
            .GetType()
            .GetProperties()
            .ToDictionary(p=>p.Name, p=> p.GetValue(obj).ToString());
}

public class ResultA
{
    public DateTime Date { get; set; }
    public int Year { get; set; }
    public int Month { get; set; }
    public int Day { get; set; }
}

Output

Key   Value
Date  10-Jun-15 14:48:11 
Year  2000 
Month 0 
Day   0 
Andrei Tătar
  • 7,872
  • 19
  • 37
  • 3
    LinqPad is a great tool! If this question helped you find that then it was well worth my time asking! – Loofer Jun 10 '15 at 13:18
13

Use reflection like this:

[Test]
public void DoStuff() {
  List<object> things = new List<object>() {
    new ResultA(){Date = DateTime.Now, Month = 34}, new ResultB(){Count = 1, Jewels = 4, Number = "2", Update = "0"}
  };

  foreach (var thing in things) {
    foreach (var property in thing.GetType().GetProperties()) {
      Trace.WriteLine(property.Name + " " + property.GetValue(thing));
    }
  }
}

Output:

Date 10.06.2015 13:46:41
Year 0
Month 34
Day 0
Number 2
Count 1
Update 0
Jewels 4

You can also use a extension method:

public static class ObjectExtensions {
  public static List<KeyValuePair<string, object>> GetProperties(this object me) {
    List<KeyValuePair<string, object>> result = new List<KeyValuePair<string, object>>();
    foreach (var property in me.GetType().GetProperties()) {
      result.Add(new KeyValuePair<string, object>(property.Name, property.GetValue(me)));
    }
    return result;
  }
}

Usage:

  [Test]
  public void DoItWithExtensionMethod() {
    List<object> things = new List<object>() {
    new ResultA(){Date = DateTime.Now, Month = 34}, new ResultB(){Count = 1, Jewels = 4, Number = "2", Update = "0"}
    };

    foreach (var thing in things) {
      var properties = thing.GetProperties();
      foreach (var property in properties) {
        Trace.WriteLine(property.Key + " " + property.Value);
      }
    }
  }
  • If you love linq that code can go into 1 line: ```public static class ObjectExtensions { public static List> GetProperties(this object me) { return me.GetType().GetProperties().Select(property => new KeyValuePair(property.Name, property.GetValue(me))).ToList(); } }``` – PandaWood Mar 20 '23 at 04:48