How can I convert a class into Dictionary<string,string>?

C#asp.netDictionary

C# Problem Overview


Can I convert Class into Dictionary<string, string>?

In Dictionary I want my class properties as keys and value of particular a property as the value.

Suppose my class is

public class Location
{
    public string city { get; set; }
    public string state { get; set; }
    public string country { get; set;
}

Now suppose my data is

city = Delhi
state = Delhi
country = India

Now you can understand my point easily!

I want to make a Dictionary! That dictionary should be like:

Dictionary<string,string> dix = new Dictionary<string,string> ();
dix.add("property_name", "property_value");

I can get the value! But how can I get property names (not value)?

What should I code to create it dynamic? That should work for every class which I want.

You can understand this question as:

How can I get a list of properties from particular class?

Now again I am explaining one of my eagernesses about Dictionary! This question popuped in my mind from answer of my previous question!!

C# Solutions


Solution 1 - C#

This is the recipe: 1 reflection, 1 LINQ-to-Objects!

 someObject.GetType()
     .GetProperties(BindingFlags.Instance | BindingFlags.Public)
          .ToDictionary(prop => prop.Name, prop => (string)prop.GetValue(someObject, null))

Since I published this answer I've checked that many people found it useful. I invite everyone looking for this simple solution to check another Q&A where I generalized it into an extension method: https://stackoverflow.com/questions/4943817/mapping-object-to-dictionary-and-vice-versa/4944547#4944547.

Solution 2 - C#

Here a example with reflection without LINQ:

    Location local = new Location();
    local.city = "Lisbon";
    local.country = "Portugal";
    local.state = "None";

    PropertyInfo[] infos = local.GetType().GetProperties();

    Dictionary<string,string> dix = new Dictionary<string,string> ();

    foreach (PropertyInfo info in infos)
    {
        dix.Add(info.Name, info.GetValue(local, null).ToString());
    }

    foreach (string key in dix.Keys)
    {
        Console.WriteLine("nameProperty: {0}; value: {1}", key, dix[key]);
    }

    Console.Read();

Solution 3 - C#

I would like to add an alternative to reflection, using JToken. You will need to check the benchmark difference between the two to see which has better performance.

var location = new Location() { City = "London" };
var locationToken = JToken.FromObject(location);
var locationObject = locationObject.Value<JObject>();
var locationPropertyList = locationObject.Properties()
    .Select(x => new KeyValuePair<string, string>(x.Name, x.Value.ToString()));

Note this method is best for a flat class structure.

Solution 4 - C#

public static Dictionary<string, object> ToDictionary(object model)
	{
		var serializedModel = JsonModelSerializer.Serialize(model);
		return JsonModelSerializer.Deserialize<Dictionary<string, object>>(serializedModel);
	}

I have used the above code. As simplified as possible and it works without reflection and the model could be nested and still work. (Change your code to not use Newtonsoft if you are using Json.net)

Solution 5 - C#

Give this a try.

This uses reflection to retrieve the object type, then all of the properties of the supplied object (PropertyInfo prop in obj.GetType().GetProperties(), see https://docs.microsoft.com/en-us/dotnet/api/system.type.getproperties?view=netcore-3.1). It then adds the property name as a key in the dictionary and, if a value exists, it adds the value, otherwise it adds null.

    public static Dictionary<string, object> ObjectToDictionary(object obj)
    {
        Dictionary<string, object> ret = new Dictionary<string, object>();

        foreach (PropertyInfo prop in obj.GetType().GetProperties())
        {
            string propName = prop.Name;
            var val = obj.GetType().GetProperty(propName).GetValue(obj, null);
            if (val != null)
            {
                ret.Add(propName, val);
            }
            else
            {
                ret.Add(propName, null);
            }
        }

        return ret;
    }

Solution 6 - C#

protected string getExamTimeBlock(object dataItem)
{
    var dt = ((System.Collections.Specialized.StringDictionary)(dataItem));

    if (SPContext.Current.Web.CurrencyLocaleID == 1033) return dt["en"];
    else return dt["sv"];
}

Solution 7 - C#

Just a gift for someone only need a simple and flat Dictionary<String,String> not requiring hierarchy or deserialize back to an object like me 

    private static readonly IDictionary<string, string> SPECIAL_FILTER_DICT = new Dictionary<string, string>
    {
        { nameof(YourEntityClass.ComplexAndCostProperty), "Some display text instead"},
        { nameof(YourEntityClass.Base64Image), ""},
        //...
    };

    
    public static IDictionary<string, string> AsDictionary(this object source, BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance)
    {
        if (source == null)
            return new Dictionary<string, string> {
                {"",""}
            };

        return source.GetType().GetProperties(bindingAttr).ToDictionary
        (
            propInfo => propInfo.Name,
            propInfo => propInfo.GetValue(source, null).GetSafeStringValue(propInfo.Name)
        );
    }


    public static String GetSafeStringValue(this object obj, String fieldName)
    {
        if (obj == null)
            return "";

        if (obj is DateTime)
            return GetStringValue((DateTime)obj);

        // More specical convert...

        if (SPECIAL_FILTER_DICT.ContainsKey(fieldName))
            return SPECIAL_FILTER_DICT[fieldName];

        // Override ToString() method if needs
        return obj.ToString();
    }


    private static String GetStringValue(DateTime dateTime)
    {
        return dateTime.ToString("YOUR DATETIME FORMAT");
    }

Solution 8 - C#

I hope this extension can be useful to someone.

public static class Ext {
	public static Dictionary<string, object> ToDict<T>(this T target)
		=> target is null
			? new Dictionary<string, object>()
			: typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public)
						.ToDictionary(
							x => x.Name,
							x => x.GetValue(target)
						);
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionChintanView Question on Stackoverflow
Solution 1 - C#Matías FidemraizerView Answer on Stackoverflow
Solution 2 - C#Bruno CostaView Answer on Stackoverflow
Solution 3 - C#Faesel SaeedView Answer on Stackoverflow
Solution 4 - C#NetProvokeView Answer on Stackoverflow
Solution 5 - C#joelcView Answer on Stackoverflow
Solution 6 - C#JonView Answer on Stackoverflow
Solution 7 - C#Nguyen Minh HienView Answer on Stackoverflow
Solution 8 - C#Vasya MilovidovView Answer on Stackoverflow