Mapping object to dictionary and vice versa
Solution 1
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
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
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
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
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...
Related videos on Youtube
Saw
Enthusiastic, highly motivated, strategic thinker, and collaborative software technologist, heavily experienced in System Architecture, Integration, and Web Development with extensive knowledge in ID document solutions and enterprise software development, product management, and project management. I enjoy challenging work environment to apply my knowledge for a forward-thinking company that embraces cutting-edge, world-class technology. London, UK
Updated on July 08, 2022Comments
-
Saw almost 2 years
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"; // ..........
-
Konrad about 4 yearsfastest way would be by code-generation like protobuf... I used expression trees to avoid reflection as often as possible
-
Cesar almost 4 yearsAll the self-coded answers below do not support deep conversion and will not work in real life applications. You should use some library like Newtonsoft as suggested by earnerplates
-
-
Matías Fidemraizer over 13 yearsFor what you want to use an activator if you can use the "new" generic constraint? :)
-
TurBas over 13 years@Matías Fidemraizer You are absolutely right. My mistake. Changed it.
-
nolimit over 11 yearsI like the implementation, I actually started using it, but do you have any feedback on performance? I know that reflection is not the greatest when it comes to performance? do you have any comments?
-
Matías Fidemraizer over 11 years@nolimit Actually I don't know its actual performance, but I guess it's not that bad (worst than avoiding reflection, of course...). In fact, what's the alternative? Depending on projects' requirements, maybe there're other options, like using dynamic typing which is far faster than reflection... Who knows! :)
-
nolimit over 11 yearswell in my case the alternative is as simple as building the object by assignment, but I'm looking for a neat yet inexpensive way to build an object. Having said that, I have found this which means to me that it's not too expensive to use that piece of code.
-
Matías Fidemraizer over 11 years@nolimit Yeah, it seems that there's no problem. It's just about using the right tool for the required problem :D In your case, it should work like a charm. I believe I can tune up something in the code yet!
-
Matías Fidemraizer over 11 years@nolimit Check that now
GetType()
isn't called onsomeObject
for each property anymore in the first method. -
Shiva over 10 yearsI guess the "best-kept secret" died a lonely death. The Castle DictionaryAdapter link above, as well as the Download links for "DictionaryAdapter" on castleproject.org all go to a 404 Page :(
-
Gaspar Nagy over 10 yearsNo! It's still in the Castle.Core. I have fixed the link.
-
regisbsb over 10 yearsI won't use it as it replaces "_" with "-". And you need MVC. Use the pure Routing class: new RouteValueDictionary(objectHere);
-
Sunil Chaudhary almost 6 yearsThanks u r awesome, one issue if someclass has not some of the properties which are in dictionary. It should match only properties exists in someclass and skip other, as of now I used try catch any better option for this?
-
baikho almost 6 yearsWhile this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value.
-
amackay11 almost 5 yearsUse this approach with caution. It will bog down your application if used for many (hundreds) of dictionaries.
-
bikeman868 almost 5 yearsCastle was a great library that got overlooked somehow
-
Cesar almost 4 yearsThis doesn't support nesting.
-
Francesco D.M. almost 4 yearsVery nice solution, but if I'm not mistaken this would not handle nested properties right?
-
Ivan Castellanos over 3 yearsThis solution doesn't work for anonymous objects (e.g when you don't have a type to convert to), for that see stackoverflow.com/a/7596697/800817
-
Adjit about 3 years@Cesar yes it does. You would just have to implement it. Maybe recursion on PropertyInfo