Convert dictionary <string, object> To Anonymous Object?

First, and to make it clearer, I will explain my scenario from above:

I have a method that has the following signature:

public virtual void SendEmail(String from, List<String> recepients, Object model) 

I want to create an anonymous object that has the properties of a model object along with the first two parameters. Smoothing a model object in PropertyInfo [] is very simple. Accordingly, I thought about creating a Dictionary that will contain PropertyInfo and the first two parameters, and then will be converted to an anonymous object, where the key is the name of the property and the value is the actual value of the property.

Is it possible? Any other suggestions?

+68
dictionary c # anonymous-types
Sep 29 2018-11-11T00:
source share
7 answers

If you really want to convert the dictionary to an object that has the elements of the dictionary as properties, you can use ExpandoObject :

 var dict = new Dictionary<string, object> { { "Property", "foo" } }; var eo = new ExpandoObject(); var eoColl = (ICollection<KeyValuePair<string, object>>)eo; foreach (var kvp in dict) { eoColl.Add(kvp); } dynamic eoDynamic = eo; string value = eoDynamic.Property; 

But I'm not sure how this will help you.

+98
Sep 29 '11 at 11:32
source share

I tried to do this in one expression using the reduce function (Aggregate in Linq). The code below does the same as the accepted answer:

 var dict = new Dictionary<string, object> { { "Property", "foo" } }; dynamic eo = dict.Aggregate(new ExpandoObject() as IDictionary<string, Object>, (a, p) => { a.Add(p.Key, p.Value); return a; }); string value = eo.Property; 
+13
Apr 14 '17 at 12:46 on
source share

If you have a class that you also want to convert to a dictionary, you can use the following to convert the dictionary into an object of this class:

Class Example:

 public class Properties1 { public string Property { get; set; } } 

Decision:

 JavaScriptSerializer serializer = new JavaScriptSerializer(); Dictionary<string, object> dict = new Dictionary<string, object> { { "Property", "foo" } }; Properties1 properties = serializer.ConvertToType<Properties1>(dict); string value = properties.Property; 



You can also use such a method to build an object from a dictionary, obviously, a class is also needed for this.

 private static T DictionaryToObject<T>(IDictionary<string, object> dict) where T : new() { T t = new T(); PropertyInfo[] properties = t.GetType().GetProperties(); foreach (PropertyInfo property in properties) { if (!dict.Any(x => x.Key.Equals(property.Name, StringComparison.InvariantCultureIgnoreCase))) continue; KeyValuePair<string, object> item = dict.First(x => x.Key.Equals(property.Name, StringComparison.InvariantCultureIgnoreCase)); Type tPropertyType = t.GetType().GetProperty(property.Name).PropertyType; Type newT = Nullable.GetUnderlyingType(tPropertyType) ?? tPropertyType; object newA = Convert.ChangeType(item.Value, newT); t.GetType().GetProperty(property.Name).SetValue(t, newA, null); } return t; } 



However, if you do not have a class, you can create a dynamic object from a dictionary, for example:

 private static dynamic DictionaryToObject(Dictionary<string, object> dict) { IDictionary<string, object> eo = (IDictionary<string, object>)new ExpandoObject(); foreach (KeyValuePair<string, object> kvp in dict) { eo.Add(kvp); } return eo; } 

You can use it like this:

 Dictionary<string, object> dict = new Dictionary<string, object> {{ "Property", "foo" }}; dynamic properties = DictionaryToObject(dict); string value = properties.Property; 
+8
Jun 24. '14 at 8:29
source share

If you want to convert Dictionary<string, object> into anonymous System.Object . You can use this method:

 public static object FromDictToAnonymousObj<TValue>(IDictionary<string, TValue> dict) { var types = new Type[dict.Count]; for (int i = 0; i < types.Length; i++) { types[i] = typeof(TValue); } // dictionaries don't have an order, so we force an order based // on the Key var ordered = dict.OrderBy(x => x.Key).ToArray(); string[] names = Array.ConvertAll(ordered, x => x.Key); Type type = AnonymousType.CreateType(types, names); object[] values = Array.ConvertAll(ordered, x => (object)x.Value); object obj = type.GetConstructor(types).Invoke(values); return obj; } 

like this:

 var dict = new Dictionary<string, string> { {"Id", "1"}, {"Title", "My title"}, {"Description", "Blah blah blah"}, }; object obj1 = FromDictToAnonymousObj(dict); 

to get your item. Where is the AnonymousType class code:

 using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Text; using System.Threading; /// <summary> /// The code generated should be nearly equal to the one generated by /// csc 12.0.31101.0 when compiling with /optimize+ /debug-. The main /// difference is in the GetHashCode() (the base init_hash used is /// compiler-dependant) and in the maxstack of the generated methods. /// Note that Roslyn (at least the one present at /// tryroslyn.azurewebsites.net) generates different code for anonymous /// types. /// </summary> public static class AnonymousType { private static readonly ConcurrentDictionary<string, Type> GeneratedTypes = new ConcurrentDictionary<string, Type>(); private static readonly AssemblyBuilder AssemblyBuilder; private static readonly ModuleBuilder ModuleBuilder; private static readonly string FileName; // Some objects we cache private static readonly CustomAttributeBuilder CompilerGeneratedAttributeBuilder = new CustomAttributeBuilder(typeof(CompilerGeneratedAttribute).GetConstructor(Type.EmptyTypes), new object[0]); private static readonly CustomAttributeBuilder DebuggerBrowsableAttributeBuilder = new CustomAttributeBuilder(typeof(DebuggerBrowsableAttribute).GetConstructor(new[] { typeof(DebuggerBrowsableState) }), new object[] { DebuggerBrowsableState.Never }); private static readonly CustomAttributeBuilder DebuggerHiddenAttributeBuilder = new CustomAttributeBuilder(typeof(DebuggerHiddenAttribute).GetConstructor(Type.EmptyTypes), new object[0]); private static readonly ConstructorInfo ObjectCtor = typeof(object).GetConstructor(Type.EmptyTypes); private static readonly MethodInfo ObjectToString = typeof(object).GetMethod("ToString", BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null); private static readonly ConstructorInfo StringBuilderCtor = typeof(StringBuilder).GetConstructor(Type.EmptyTypes); private static readonly MethodInfo StringBuilderAppendString = typeof(StringBuilder).GetMethod("Append", BindingFlags.Instance | BindingFlags.Public, null, new[] { typeof(string) }, null); private static readonly MethodInfo StringBuilderAppendObject = typeof(StringBuilder).GetMethod("Append", BindingFlags.Instance | BindingFlags.Public, null, new[] { typeof(object) }, null); private static readonly Type EqualityComparer = typeof(EqualityComparer<>); private static readonly Type EqualityComparerGenericArgument = EqualityComparer.GetGenericArguments()[0]; private static readonly MethodInfo EqualityComparerDefault = EqualityComparer.GetMethod("get_Default", BindingFlags.Static | BindingFlags.Public, null, Type.EmptyTypes, null); private static readonly MethodInfo EqualityComparerEquals = EqualityComparer.GetMethod("Equals", BindingFlags.Instance | BindingFlags.Public, null, new[] { EqualityComparerGenericArgument, EqualityComparerGenericArgument }, null); private static readonly MethodInfo EqualityComparerGetHashCode = EqualityComparer.GetMethod("GetHashCode", BindingFlags.Instance | BindingFlags.Public, null, new[] { EqualityComparerGenericArgument }, null); private static int Index = -1; static AnonymousType() { var assemblyName = new AssemblyName("AnonymousTypes"); FileName = assemblyName.Name + ".dll"; AssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); ModuleBuilder = AssemblyBuilder.DefineDynamicModule("AnonymousTypes", FileName); } public static void Dump() { AssemblyBuilder.Save(FileName); } /// <summary> /// /// </summary> /// <param name="types"></param> /// <param name="names"></param> /// <returns></returns> public static Type CreateType(Type[] types, string[] names) { if (types == null) { throw new ArgumentNullException("types"); } if (names == null) { throw new ArgumentNullException("names"); } if (types.Length != names.Length) { throw new ArgumentException("names"); } // Anonymous classes are generics based. The generic classes // are distinguished by number of parameters and name of // parameters. The specific types of the parameters are the // generic arguments. We recreate this by creating a fullName // composed of all the property names, separated by a "|" string fullName = string.Join("|", names.Select(x => Escape(x))); Type type; if (!GeneratedTypes.TryGetValue(fullName, out type)) { // We create only a single class at a time, through this lock // Note that this is a variant of the double-checked locking. // It is safe because we are using a thread safe class. lock (GeneratedTypes) { if (!GeneratedTypes.TryGetValue(fullName, out type)) { int index = Interlocked.Increment(ref Index); string name = names.Length != 0 ? string.Format("<>f__AnonymousType{0}`{1}", index, names.Length) : string.Format("<>f__AnonymousType{0}", index); TypeBuilder tb = ModuleBuilder.DefineType(name, TypeAttributes.AnsiClass | TypeAttributes.Class | TypeAttributes.AutoLayout | TypeAttributes.NotPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit); tb.SetCustomAttribute(CompilerGeneratedAttributeBuilder); GenericTypeParameterBuilder[] generics = null; if (names.Length != 0) { string[] genericNames = Array.ConvertAll(names, x => string.Format("<{0}>j__TPar", x)); generics = tb.DefineGenericParameters(genericNames); } else { generics = new GenericTypeParameterBuilder[0]; } // .ctor ConstructorBuilder constructor = tb.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig, CallingConventions.HasThis, generics); constructor.SetCustomAttribute(DebuggerHiddenAttributeBuilder); ILGenerator ilgeneratorConstructor = constructor.GetILGenerator(); ilgeneratorConstructor.Emit(OpCodes.Ldarg_0); ilgeneratorConstructor.Emit(OpCodes.Call, ObjectCtor); var fields = new FieldBuilder[names.Length]; // There are two for cycles because we want to have // all the getter methods before all the other // methods for (int i = 0; i < names.Length; i++) { // field fields[i] = tb.DefineField(string.Format("<{0}>i__Field", names[i]), generics[i], FieldAttributes.Private | FieldAttributes.InitOnly); fields[i].SetCustomAttribute(DebuggerBrowsableAttributeBuilder); // .ctor constructor.DefineParameter(i + 1, ParameterAttributes.None, names[i]); ilgeneratorConstructor.Emit(OpCodes.Ldarg_0); if (i == 0) { ilgeneratorConstructor.Emit(OpCodes.Ldarg_1); } else if (i == 1) { ilgeneratorConstructor.Emit(OpCodes.Ldarg_2); } else if (i == 2) { ilgeneratorConstructor.Emit(OpCodes.Ldarg_3); } else if (i < 255) { ilgeneratorConstructor.Emit(OpCodes.Ldarg_S, (byte)(i + 1)); } else { // Ldarg uses a ushort, but the Emit only // accepts short, so we use a unchecked(...), // cast to short and let the CLR interpret it // as ushort ilgeneratorConstructor.Emit(OpCodes.Ldarg, unchecked((short)(i + 1))); } ilgeneratorConstructor.Emit(OpCodes.Stfld, fields[i]); // getter MethodBuilder getter = tb.DefineMethod(string.Format("get_{0}", names[i]), MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName, CallingConventions.HasThis, generics[i], Type.EmptyTypes); ILGenerator ilgeneratorGetter = getter.GetILGenerator(); ilgeneratorGetter.Emit(OpCodes.Ldarg_0); ilgeneratorGetter.Emit(OpCodes.Ldfld, fields[i]); ilgeneratorGetter.Emit(OpCodes.Ret); PropertyBuilder property = tb.DefineProperty(names[i], PropertyAttributes.None, CallingConventions.HasThis, generics[i], Type.EmptyTypes); property.SetGetMethod(getter); } // ToString() MethodBuilder toString = tb.DefineMethod("ToString", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, CallingConventions.HasThis, typeof(string), Type.EmptyTypes); toString.SetCustomAttribute(DebuggerHiddenAttributeBuilder); ILGenerator ilgeneratorToString = toString.GetILGenerator(); ilgeneratorToString.DeclareLocal(typeof(StringBuilder)); ilgeneratorToString.Emit(OpCodes.Newobj, StringBuilderCtor); ilgeneratorToString.Emit(OpCodes.Stloc_0); // Equals MethodBuilder equals = tb.DefineMethod("Equals", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, CallingConventions.HasThis, typeof(bool), new[] { typeof(object) }); equals.SetCustomAttribute(DebuggerHiddenAttributeBuilder); equals.DefineParameter(1, ParameterAttributes.None, "value"); ILGenerator ilgeneratorEquals = equals.GetILGenerator(); ilgeneratorEquals.DeclareLocal(tb); ilgeneratorEquals.Emit(OpCodes.Ldarg_1); ilgeneratorEquals.Emit(OpCodes.Isinst, tb); ilgeneratorEquals.Emit(OpCodes.Stloc_0); ilgeneratorEquals.Emit(OpCodes.Ldloc_0); Label equalsLabel = ilgeneratorEquals.DefineLabel(); // GetHashCode() MethodBuilder getHashCode = tb.DefineMethod("GetHashCode", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, CallingConventions.HasThis, typeof(int), Type.EmptyTypes); getHashCode.SetCustomAttribute(DebuggerHiddenAttributeBuilder); ILGenerator ilgeneratorGetHashCode = getHashCode.GetILGenerator(); ilgeneratorGetHashCode.DeclareLocal(typeof(int)); if (names.Length == 0) { ilgeneratorGetHashCode.Emit(OpCodes.Ldc_I4_0); } else { // As done by Roslyn // Note that initHash can vary, because // string.GetHashCode() isn't "stable" for // different compilation of the code int initHash = 0; for (int i = 0; i < names.Length; i++) { initHash = unchecked(initHash * (-1521134295) + fields[i].Name.GetHashCode()); } // Note that the CSC seems to generate a // different seed for every anonymous class ilgeneratorGetHashCode.Emit(OpCodes.Ldc_I4, initHash); } for (int i = 0; i < names.Length; i++) { // Equals() Type equalityComparerT = EqualityComparer.MakeGenericType(generics[i]); MethodInfo equalityComparerTDefault = TypeBuilder.GetMethod(equalityComparerT, EqualityComparerDefault); MethodInfo equalityComparerTEquals = TypeBuilder.GetMethod(equalityComparerT, EqualityComparerEquals); ilgeneratorEquals.Emit(OpCodes.Brfalse_S, equalsLabel); ilgeneratorEquals.Emit(OpCodes.Call, equalityComparerTDefault); ilgeneratorEquals.Emit(OpCodes.Ldarg_0); ilgeneratorEquals.Emit(OpCodes.Ldfld, fields[i]); ilgeneratorEquals.Emit(OpCodes.Ldloc_0); ilgeneratorEquals.Emit(OpCodes.Ldfld, fields[i]); ilgeneratorEquals.Emit(OpCodes.Callvirt, equalityComparerTEquals); // GetHashCode(); MethodInfo EqualityComparerTGetHashCode = TypeBuilder.GetMethod(equalityComparerT, EqualityComparerGetHashCode); ilgeneratorGetHashCode.Emit(OpCodes.Stloc_0); ilgeneratorGetHashCode.Emit(OpCodes.Ldc_I4, -1521134295); ilgeneratorGetHashCode.Emit(OpCodes.Ldloc_0); ilgeneratorGetHashCode.Emit(OpCodes.Mul); ilgeneratorGetHashCode.Emit(OpCodes.Call, EqualityComparerDefault); ilgeneratorGetHashCode.Emit(OpCodes.Ldarg_0); ilgeneratorGetHashCode.Emit(OpCodes.Ldfld, fields[i]); ilgeneratorGetHashCode.Emit(OpCodes.Callvirt, EqualityComparerGetHashCode); ilgeneratorGetHashCode.Emit(OpCodes.Add); // ToString() ilgeneratorToString.Emit(OpCodes.Ldloc_0); ilgeneratorToString.Emit(OpCodes.Ldstr, i == 0 ? string.Format("{{ {0} = ", names[i]) : string.Format(", {0} = ", names[i])); ilgeneratorToString.Emit(OpCodes.Callvirt, StringBuilderAppendString); ilgeneratorToString.Emit(OpCodes.Pop); ilgeneratorToString.Emit(OpCodes.Ldloc_0); ilgeneratorToString.Emit(OpCodes.Ldarg_0); ilgeneratorToString.Emit(OpCodes.Ldfld, fields[i]); ilgeneratorToString.Emit(OpCodes.Box, generics[i]); ilgeneratorToString.Emit(OpCodes.Callvirt, StringBuilderAppendObject); ilgeneratorToString.Emit(OpCodes.Pop); } // .ctor ilgeneratorConstructor.Emit(OpCodes.Ret); // Equals() if (names.Length == 0) { ilgeneratorEquals.Emit(OpCodes.Ldnull); ilgeneratorEquals.Emit(OpCodes.Ceq); ilgeneratorEquals.Emit(OpCodes.Ldc_I4_0); ilgeneratorEquals.Emit(OpCodes.Ceq); } else { ilgeneratorEquals.Emit(OpCodes.Ret); ilgeneratorEquals.MarkLabel(equalsLabel); ilgeneratorEquals.Emit(OpCodes.Ldc_I4_0); } ilgeneratorEquals.Emit(OpCodes.Ret); // GetHashCode() ilgeneratorGetHashCode.Emit(OpCodes.Stloc_0); ilgeneratorGetHashCode.Emit(OpCodes.Ldloc_0); ilgeneratorGetHashCode.Emit(OpCodes.Ret); // ToString() ilgeneratorToString.Emit(OpCodes.Ldloc_0); ilgeneratorToString.Emit(OpCodes.Ldstr, names.Length == 0 ? "{ }" : " }"); ilgeneratorToString.Emit(OpCodes.Callvirt, StringBuilderAppendString); ilgeneratorToString.Emit(OpCodes.Pop); ilgeneratorToString.Emit(OpCodes.Ldloc_0); ilgeneratorToString.Emit(OpCodes.Callvirt, ObjectToString); ilgeneratorToString.Emit(OpCodes.Ret); type = tb.CreateType(); type = GeneratedTypes.GetOrAdd(fullName, type); } } } if (types.Length != 0) { type = type.MakeGenericType(types); } return type; } private static string Escape(string str) { // We escape the \ with \\, so that we can safely escape the // "|" (that we use as a separator) with "\|" str = str.Replace(@"\", @"\\"); str = str.Replace(@"|", @"\|"); return str; } } 

Link: stack overflow

+4
02 Oct '15 at 7:21
source share

A slightly more modular version of the svick response using several extension methods:

 public static class Extensions { public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> items) { foreach (var item in items) { collection.Add(item); } } public static dynamic ToDynamicObject(this IDictionary<string, object> source) { ICollection<KeyValuePair<string, object>> someObject = new ExpandoObject(); someObject.AddRange(source); return someObject; } } 
+4
Dec 17 '15 at 12:33
source share

Anonymous objects are those that the compiler generated for you. You cannot dynamically generate them. On the other hand, you can emit such an object, but I really do not think this is a good idea.

Maybe you can try dynamic objects? The result will be an object with all the necessary properties.

+3
Sep 29 2018-11-11T00:
source share

Credit here goes to the accepted answer. Adding this because I wanted to turn List <Dictionary <string, object >> into List <dynamic>. The goal is to extract records from the database table. Here is what I did.

  public static List<dynamic> ListDictionaryToListDynamic(List<Dictionary<string,object>> dbRecords) { var eRecords = new List<dynamic>(); foreach (var record in dbRecords) { var eRecord = new ExpandoObject() as IDictionary<string, object>; foreach (var kvp in record) { eRecord.Add(kvp); } eRecords.Add(eRecord); } return eRecords; } 
+1
Jan 14 '19 at 15:49
source share



All Articles