Mapping object to dictionary and vice versa

C#.NetDictionaryReflectionMapping

C# Problem Overview


Are there any elegant quick way to map object to a dictionary and vice versa?

Example:
IDictionary<string,object> a = new Dictionary<string,object>();
a["Id"]=1;
a["Name"]="Ahmad";
// .....

becomes

SomeClass b = new SomeClass();
b.Id=1;
b.Name="Ahmad";
// ..........

C# Solutions


Solution 1 - C#

Using some reflection and generics in two extension methods you can achieve that.

Right, others did mostly the same solution, but this uses less reflection which is more performance-wise and way more readable:

public static class ObjectExtensions
{
    public static T ToObject<T>(this IDictionary<string, object> source)
        where T : class, new()
    {
            var someObject = new T();
            var someObjectType = someObject.GetType();

            foreach (var item in source)
            {
                someObjectType
                         .GetProperty(item.Key)
                         .SetValue(someObject, item.Value, null);
            }

            return someObject;
    }

    public static IDictionary<string, object> AsDictionary(this object source, BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance)
    {
        return source.GetType().GetProperties(bindingAttr).ToDictionary
        (
            propInfo => propInfo.Name,
            propInfo => propInfo.GetValue(source, null)
        );
                        
    }
}

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

    public int Prop2
    {
        get;
        set;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Dictionary<string, object> dictionary = new Dictionary<string, object>();
        dictionary.Add("Prop1", "hello world!");
        dictionary.Add("Prop2", 3893);
        A someObject = dictionary.ToObject<A>();

        IDictionary<string, object> objectBackToDictionary = someObject.AsDictionary();
    }
}

Solution 2 - C#

Convert the Dictionary to JSON string first with Newtonsoft.

var json = JsonConvert.SerializeObject(advancedSettingsDictionary, Newtonsoft.Json.Formatting.Indented);

Then deserialize the JSON string to your object

var myobject = JsonConvert.DeserializeObject<AOCAdvancedSettings>(json);
                

Solution 3 - C#

Seems reflection only help here.. I've done small example of converting object to dictionary and vise versa:

[TestMethod]
public void DictionaryTest()
{
    var item = new SomeCLass { Id = "1", Name = "name1" };
    IDictionary<string, object> dict = ObjectToDictionary<SomeCLass>(item);
    var obj = ObjectFromDictionary<SomeCLass>(dict);
}

private T ObjectFromDictionary<T>(IDictionary<string, object> dict)
    where T : class 
{
    Type type = typeof(T);
    T result = (T)Activator.CreateInstance(type);
    foreach (var item in dict)
    {
        type.GetProperty(item.Key).SetValue(result, item.Value, null);
    }
    return result;
}

private IDictionary<string, object> ObjectToDictionary<T>(T item)
    where T: class
{
    Type myObjectType = item.GetType();
    IDictionary<string, object> dict = new Dictionary<string, object>();
    var indexer = new object[0];
    PropertyInfo[] properties = myObjectType.GetProperties();
    foreach (var info in properties)
    {
        var value = info.GetValue(item, indexer);
        dict.Add(info.Name, value);
    }
    return dict;
}

Solution 4 - C#

I'd highly recommend the Castle DictionaryAdapter, easily one of that project's best-kept secrets. You only need to define an interface with the properties you want, and in one line of code the adapter will generate an implementation, instantiate it, and synchronize its values with a dictionary you pass in. I use it to strongly-type my AppSettings in a web project:

var appSettings =
  new DictionaryAdapterFactory().GetAdapter<IAppSettings>(ConfigurationManager.AppSettings);

Note that I did not need to create a class that implements IAppSettings - the adapter does that on the fly. Also, although in this case I'm only reading, in theory if I were setting property values on appSettings, the adapter would keep the underlying dictionary in sync with those changes.

Solution 5 - C#

Reflection can take you from an object to a dictionary by iterating over the properties.

To go the other way, you'll have to use a dynamic ExpandoObject (which, in fact, already inherits from IDictionary, and so has done this for you) in C#, unless you can infer the type from the collection of entries in the dictionary somehow.

So, if you're in .NET 4.0 land, use an ExpandoObject, otherwise you've got a lot of work to do...

Solution 6 - C#

I think you should use reflection. Something like this:

private T ConvertDictionaryTo<T>(IDictionary<string, object> dictionary) where T : new()
{
    Type type = typeof (T);
    T ret = new T();

    foreach (var keyValue in dictionary)
    {
        type.GetProperty(keyValue.Key).SetValue(ret, keyValue.Value, null);
    }

    return ret;
}

It takes your dictionary and loops through it and sets the values. You should make it better but it's a start. You should call it like this:

SomeClass someClass = ConvertDictionaryTo<SomeClass>(a);

Solution 7 - C#

public class SimpleObjectDictionaryMapper<TObject>
{
    public static TObject GetObject(IDictionary<string, object> d)
    {
        PropertyInfo[] props = typeof(TObject).GetProperties();
        TObject res = Activator.CreateInstance<TObject>();
        for (int i = 0; i < props.Length; i++)
        {
            if (props[i].CanWrite && d.ContainsKey(props[i].Name))
            {
                props[i].SetValue(res, d[props[i].Name], null);
            }
        }
        return res;
    }

    public static IDictionary<string, object> GetDictionary(TObject o)
    {
        IDictionary<string, object> res = new Dictionary<string, object>();
        PropertyInfo[] props = typeof(TObject).GetProperties();
        for (int i = 0; i < props.Length; i++)
        {
            if (props[i].CanRead)
            {
                res.Add(props[i].Name, props[i].GetValue(o, null));
            }
        }
        return res;
    }
}

Solution 8 - C#

Building on Matías Fidemraizer's answer, here is a version that supports binding to object properties other than strings.

using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace WebOpsApi.Shared.Helpers
{
	public static class MappingExtension
	{
		public static T ToObject<T>(this IDictionary<string, object> source)
			where T : class, new()
		{
			var someObject = new T();
			var someObjectType = someObject.GetType();

			foreach (var item in source)
			{
				var key = char.ToUpper(item.Key[0]) + item.Key.Substring(1);
				var targetProperty = someObjectType.GetProperty(key);

				//edited this line
				if (targetProperty.PropertyType == item.Value.GetType())
				{
					targetProperty.SetValue(someObject, item.Value);
				}
				else
				{

					var parseMethod = targetProperty.PropertyType.GetMethod("TryParse",
						BindingFlags.Public | BindingFlags.Static, null,
						new[] {typeof (string), targetProperty.PropertyType.MakeByRefType()}, null);
					
					if (parseMethod != null)
					{
						var parameters = new[] { item.Value, null };
						var success = (bool)parseMethod.Invoke(null, parameters);
						if (success)
						{
							targetProperty.SetValue(someObject, parameters[1]);
						}

					}
				}
			}

			return someObject;
		}

		public static IDictionary<string, object> AsDictionary(this object source, BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance)
		{
			return source.GetType().GetProperties(bindingAttr).ToDictionary
			(
				propInfo => propInfo.Name,
				propInfo => propInfo.GetValue(source, null)
			);
		}
	}
}

Solution 9 - C#

If you are using Asp.Net MVC, then take a look at:

public static RouteValueDictionary AnonymousObjectToHtmlAttributes(object htmlAttributes);

which is a static public method on the System.Web.Mvc.HtmlHelper class.

Solution 10 - C#

    public Dictionary<string, object> ToDictionary<T>(string key, T value)
    {
        try
        {
            var payload = new Dictionary<string, object>
            {
                { key, value }
            }; 
        } catch (Exception e)
        {
            return null;
        }
    }

    public T FromDictionary<T>(Dictionary<string, object> payload, string key)
    {
        try
        {
            JObject jObject = (JObject) payload[key];
            T t = jObject.ToObject<T>();
            return (t);
        }
        catch(Exception e) {
            return default(T);
        }
    }

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
QuestionSawanView Question on Stackoverflow
Solution 1 - C#Matías FidemraizerView Answer on Stackoverflow
Solution 2 - C#learnerplatesView Answer on Stackoverflow
Solution 3 - C#Andrew OrsichView Answer on Stackoverflow
Solution 4 - C#Todd MenierView Answer on Stackoverflow
Solution 5 - C#MassifView Answer on Stackoverflow
Solution 6 - C#TurBasView Answer on Stackoverflow
Solution 7 - C#SawanView Answer on Stackoverflow
Solution 8 - C#Daniel LewisView Answer on Stackoverflow
Solution 9 - C#magritteView Answer on Stackoverflow
Solution 10 - C#Williams AbiolaView Answer on Stackoverflow