List<T> to a Dictionary - c#

I have a List<CustomObject>
which has 3 properties
A,B,C
and what I need is to transform this List to a Dictionary so the result looks like
Dictionary<string,object>
(Property name) A = Value of A
(Property name) B = Value of B
(Property name) C = Value of C
Pls suggest...

CustomObject instance = new CustomObject();
var dict = instance.GetType().GetProperties()
.ToDictionary(p => p.Name, p => p.GetValue(instance, null));

I found the code :) Originally from here.
static T CreateDelegate<T>(this DynamicMethod dm) where T : class
{
return dm.CreateDelegate(typeof(T)) as T;
}
static Dictionary<Type, Func<object, Dictionary<string, object>>> cache =
new Dictionary<Type, Func<object, Dictionary<string, object>>>();
static Dictionary<string, object> GetProperties(object o)
{
var t = o.GetType();
Func<object, Dictionary<string, object>> getter;
if (!cache.TryGetValue(t, out getter))
{
var rettype = typeof(Dictionary<string, object>);
var dm = new DynamicMethod(t.Name + ":GetProperties", rettype,
new Type[] { typeof(object) }, t);
var ilgen = dm.GetILGenerator();
var instance = ilgen.DeclareLocal(t);
var dict = ilgen.DeclareLocal(rettype);
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Castclass, t);
ilgen.Emit(OpCodes.Stloc, instance);
ilgen.Emit(OpCodes.Newobj, rettype.GetConstructor(Type.EmptyTypes));
ilgen.Emit(OpCodes.Stloc, dict);
var add = rettype.GetMethod("Add");
foreach (var prop in t.GetProperties(
BindingFlags.Instance |
BindingFlags.Public))
{
ilgen.Emit(OpCodes.Ldloc, dict);
ilgen.Emit(OpCodes.Ldstr, prop.Name);
ilgen.Emit(OpCodes.Ldloc, instance);
ilgen.Emit(OpCodes.Ldfld, prop);
ilgen.Emit(OpCodes.Castclass, typeof(object));
ilgen.Emit(OpCodes.Callvirt, add);
}
ilgen.Emit(OpCodes.Ldloc, dict);
ilgen.Emit(OpCodes.Ret);
cache[t] = getter =
dm.CreateDelegate<Func<object, Dictionary<string, object>>>();
}
return getter(o);
}
For given type:
class Foo
{
public string A {get;}
public int B {get;}
public bool C {get;}
}
It produces a delegate equivalent to:
(Foo f) => new Dictionary<string, object>
{
{ "A", f.A },
{ "B", f.B },
{ "C", f.C },
};
Disclaimer: Looking at the code now (without testing) there may need to be special handling for valuetypes (instead of just the castclass). Exercise for the reader.

If I understand correctly what you want to do, you have to use reflrecion on CustomObject to get the property names then simply create the dictionary:
dic.add(propertyName, value);

Related

Linq - How to query Dictionary<int,object>

I want to be able to query and sort a Dictionary<int, MyObj> by any of the properties inside MyObj.
class MyObj
{
public string Symbol { get; set; }
public string Name { get; set; }
public int AtomicNumber { get; set; }
public int Id { get; set; }
public string toString()
{
return Symbol + " " + Name + " " + AtomicNumber + " " + Id;
}
}
class Program
{
private static void AddToDictionary(Dictionary<int, MyObj> elements,
string symbol, string name, int atomicNumber, int id)
{
MyObj theElement = new MyObj();
theElement.Symbol = symbol;
theElement.Name = name;
theElement.AtomicNumber = atomicNumber;
theElement.Id = id;
elements.Add(key: theElement.Id, value: theElement);
}
private static Dictionary<int, MyObj> BuildDictionary()
{
var elements = new Dictionary<int, MyObj>();
AddToDictionary(elements, "K", "Potassium", 19, 0);
AddToDictionary(elements, "Ca", "Calcium", 20, 1);
AddToDictionary(elements, "Sc", "Scandium", 21, 2);
AddToDictionary(elements, "Ti", "Titanium", 22, 3);
return elements;
}
static List<T> GetListOfProperty<T>(Dictionary<int, MyObj> colBlobs, string property)
{
Type t = typeof(MyObj);
PropertyInfo prop = t.GetProperty(property);
if (prop == null)
{
// throw new Exception(string.Format("Property {0} not found", f.Name.ToLower()));
Console.WriteLine(string.Format("Property {0} not found", property));
return new List<T>();
}
//still need to fix this
return colBlobs.Values
.Select(blob => (T)prop.GetValue(blob))
.OrderBy(x => x)
.ToList();
}
static SortedDictionary<int, MyObj> GetListOfProperty2<T>(Dictionary<int, MyObj> colBlobs, string property)
{
// CODE?
return sortedDict;
}
static void Main(string[] args)
{
Dictionary<int, MyObj> myColl = BuildDictionary();
var res = GetListOfProperty<string>(myColl, "Name");
foreach (var rr in res)
Console.WriteLine(rr.ToString());
//outputs : Which is only one property, the one selected
//--------
//Calcium
//Potassium
//Scandium
//Titanium
var res2 = GetListOfProperty2<string>(myColl, "Name");
//want to output the whole dictionary
//<1, {"Ca", "Calcium", 20,1}
//<0, {"K", "Potassium", 19, 0}
//<2, {"Sc", "Scandium", 21, 2}
//<3, {"Ti", "Titanium", 22, 3}
}
}
Since it seems to be that it is unclear what I want. I added example output. I am pretty sure there is no way to make this question more clear.
The problem with SortedDictionary is that it can only be sorted by Key, so you'll have to use OrderBy() in some way:
public static IOrderedEnumerable<KeyValuePair<K, T>> SortByMember<K, T>(this Dictionary<K, T> data, string memberName)
{
Type type = typeof(T);
MemberInfo info = type.GetProperty(memberName) ?? type.GetField(memberName) as MemberInfo;
Func<KeyValuePair<K, T>, object> getter = kvp => kvp.Key;
if (info is PropertyInfo pi)
getter = kvp => pi.GetValue(kvp.Value);
else if (info is FieldInfo fi)
getter = kvp => fi.GetValue(kvp.Value);
return data.OrderBy(getter);
}
This can handle both properties and fields, and if the member name is invalid, it defaults to sorting by key.
You can change that to not sort if member name is invalid by changing the return value:
public static IEnumerable<KeyValuePair<K, T>> SortByMember<K, T>(this Dictionary<K, T> data, string memberName)
{
Type type = typeof(T);
MemberInfo info = type.GetProperty(memberName) ?? type.GetField(memberName) as MemberInfo;
if (info == null) return data;
Func<KeyValuePair<K, T>, object> getter = null;
if (info is PropertyInfo pi)
getter = kvp => pi.GetValue(kvp.Value);
else if (info is FieldInfo fi)
getter = kvp => fi.GetValue(kvp.Value);
return data.OrderBy(getter);
}
IMO it is wrong to return an empty dictionary if it fails to find the member. Alternatively you can throw an exception.
Use case:
Dictionary<int, MyObj> myColl = BuildDictionary();
var res = myColl.SortByMember("Name");
foreach (var rr in res)
Console.WriteLine(rr.Value);
To achieve your goal you can use expression tree to build a compiled lambda and then use this lambda in the Linq OrderBy() method:
public static class ExpressionHelper
{
public static Func<T, object> GetMemberExpressionFunc<T>(string memberName)
{
var parameter = Expression.Parameter(typeof(T));
Expression source = Expression.PropertyOrField(parameter, memberName);
Expression conversion = Expression.Convert(source, typeof(object));
return Expression.Lambda<Func<T, object>>(conversion, parameter).Compile();
}
}
static void Main(string[] args)
{
Dictionary<int, MyObj> myColl = BuildDictionary();
string property = "AtomicNumber"; // or whatever property you want your dictionary ordered by
var func = ExpressionHelper.GetMemberExpressionFunc<MyObj>(property);
var ordered = myColl.OrderBy(x => func(x.Value));
}

get and set object property using Expression trees instead of Reflection

I would like to dynamically get and set an objects properties as follows:
public class Person
{
public string Name {get; set; }
}
public class Testing
{
public void Run()
{
var p = new Person();
SetValue(p, "Name", "Henry");
var name = GetValue(p, "Name");
}
}
Please could I get help creating the GetValue and SetValue methods using dynamic method (or expression trees)?
I am intending to save compiled expressions in a dictionary, to speed up future get/set calls.
Do you really want to use expression trees? for this simple scenario I would try to compile directly into a DynamicMethod using Reflection.Emit API's by getting an IL Generator. But .. for expression trees, i wrote a helper for you:
public class PropertyManager : DynamicObject
{
private static Dictionary<Type, Dictionary<string, GetterAndSetter>> _compiledProperties = new Dictionary<Type, Dictionary<string, GetterAndSetter>>();
private static Object _compiledPropertiesLockObject = new object();
private class GetterAndSetter
{
public Action<object, Object> Setter { get; set; }
public Func<Object, Object> Getter { get; set; }
}
private Object _object;
private Type _objectType;
private PropertyManager(Object o)
{
_object = o;
_objectType = o.GetType();
}
public static dynamic Wrap(Object o)
{
if (o == null)
return null; // null reference will be thrown
var type = o.GetType();
EnsurePropertySettersAndGettersForType(type);
return new PropertyManager(o) as dynamic;
}
private static void EnsurePropertySettersAndGettersForType(Type type)
{
if (false == _compiledProperties.ContainsKey(type))
lock (_compiledPropertiesLockObject)
if (false == _compiledProperties.ContainsKey(type))
{
Dictionary<string, GetterAndSetter> _getterAndSetters;
_compiledProperties[type] = _getterAndSetters = new Dictionary<string, GetterAndSetter>();
var properties = type.GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic);
foreach (var property in properties)
{
var getterAndSetter = new GetterAndSetter();
_getterAndSetters[property.Name] = getterAndSetter;
// burn getter and setter
if (property.CanRead)
{
// burn getter
var param = Expression.Parameter(typeof(object), "param");
Expression propExpression = Expression.Convert(Expression.Property(Expression.Convert(param, type), property), typeof(object));
var lambda = Expression.Lambda(propExpression, new[] { param });
var compiled = lambda.Compile() as Func<object, object>;
getterAndSetter.Getter = compiled;
}
if (property.CanWrite)
{
var thisParam = Expression.Parameter(typeof(Object), "this");
var theValue = Expression.Parameter(typeof(Object), "value");
var isValueType = property.PropertyType.IsClass == false && property.PropertyType.IsInterface == false;
Expression valueExpression;
if (isValueType)
valueExpression = Expression.Unbox(theValue, property.PropertyType);
else
valueExpression = Expression.Convert(theValue, property.PropertyType);
var thisExpression = Expression.Property (Expression.Convert(thisParam, type), property);
Expression body = Expression.Assign(thisExpression, valueExpression);
var block = Expression.Block(new[]
{
body,
Expression.Empty ()
});
var lambda = Expression.Lambda(block, thisParam, theValue);
getterAndSetter.Setter = lambda.Compile() as Action<Object, Object>;
}
}
}
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
var memberName = binder.Name;
result = null;
Dictionary<string, GetterAndSetter> dict;
GetterAndSetter getterAndSetter;
if (false == _compiledProperties.TryGetValue(_objectType, out dict)
|| false == dict.TryGetValue(memberName, out getterAndSetter))
{
return false;
}
if (getterAndSetter.Getter == null)
throw new NotSupportedException("The property has no getter!");
result = getterAndSetter.Getter(_object);
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
var memberName = binder.Name;
Dictionary<string, GetterAndSetter> dict;
GetterAndSetter getterAndSetter;
if (false == _compiledProperties.TryGetValue(_objectType, out dict)
|| false == dict.TryGetValue(memberName, out getterAndSetter))
{
return false;
}
if (getterAndSetter.Setter == null)
throw new NotSupportedException("The property has no getter!");
getterAndSetter.Setter(_object, value);
return true;
}
}
And this is how you can use it:
Person p = new Person();
p.Name = "mama";
var wrapped = PropertyManager.Wrap(p);
var val = wrapped.Name; // here we are using our compiled method ...
It is very obvious that you can extract my compilation logic to use strings instead of letting DLR giving the property name for you :)

Reflecting dynamic functions

I have created a method that inspects an object and returns a [requested] set of properties.
public static List<object> Inspect<T>(T obj, params Func<T, object>[] funcs)
{
List<object> results = new List<object>(funcs.Length);
foreach (var func in funcs)
{
results.Add(func(obj));
}
return results;
}
It is then invoked, for example on a List, like so:
List<string> peopleData = new List<string>(10) { "name", "age", "address" };
List<object> properties = Inspect(peopleData, p => p.Count, p => p.Capacity);
// The results would be
// properties[0] = 3
// properties[1] = 10
I would like to adapt the Inspect method to instead return a Dictionary<string, object>, where the keys of the dictionary would be the property names. The adapted method would then be invoked like this:
List<string> peopleData = new List<string>(10) { "name", "age", "address" };
Dictionary<string, object> properties = Inspect(peopleData, p => p.Count, p => p.Capacity);
// The results would be
// properties["Count"] = 3
// properties["Capacity"] = 10
Is this possible? If so, and if the solution is reflection-based (as I assume it'd have to be), would there be a big performance hit?
You'd have to use the classic "interrogation" approach for Func<..> - Retrieving Property name from lambda expression
public static IDictionary<string, object> Inspect<T>(T obj,
params Expression<Func<T, object>>[] funcs)
{
Dictionary<string, object> results = new Dictionary<string, object>();
foreach (var func in funcs)
{
var propInfo = GetPropertyInfo(obj, func)
results[propInfo.Name] = func.Compile()(obj));
}
return results;
}
Ps, as Servy pointed out, you'd also need to make the params use Expression.

Expression for read from property and write to private readonly field

It is a long story ): I have some types look like this:
public class Model {
private readonly SomeType _member;
private readonly AnotherType _member2;
public Model(SomeType member, AnotherType member2) {
_member = member;
_member2 = member2;
}
public SomeType Member { get { return _member; } }
public AnotherType Member2 { get { return _member2; } }
}
I'm trying to create some expressions to create an instance of class, reads properties from some other objects (anon objects usually), and write the values to created instance's private fields -based on shown naming convention: Prop has field name: _prop.
I mean I want to write below objects to a new instance of Model:
var anon1 = new { Member = "something" };
// expected: new Model with _member = "something"
var anon2 = new { Member2 = "something" };
// expected: new Model with _member2 = "something"
var anon3 = new { Member = "something", Member2 = "something else" };
// expected: new Model with _member = "something" and _member2 = "something else"
I have created below code, it creates new instances, but do nothing with fields. Can you help me to find where I did wrong please?
public class InstanceCreator {
static public readonly Func<FieldInfo, PropertyInfo, bool> NamingConvention;
static InstanceCreator() {
NamingConvention = (f, p) => {
var startsWithUnderscope = f.Name.StartsWith("_");
var hasSameName = p.Name.Equals(f.Name.Remove(0, 1), StringComparison.OrdinalIgnoreCase);
var hasSameType = f.FieldType == p.PropertyType;
return startsWithUnderscope && hasSameName && hasSameType &&
f.IsInitOnly && !p.CanWrite;
};
}
private readonly Type _type;
private readonly Func<dynamic, dynamic> _creator;
public InstanceCreator(Type type) {
_type = type;
var ctor = GetCtor(type);
var propertyToFieldWriters = MakeWriters(type);
_creator = MakeCreator(type, ctor, propertyToFieldWriters);
}
private Expression GetCtor(Type type) {
if (type == typeof(string)) // ctor for string
return Expression.Lambda<Func<dynamic>>(
Expression.Constant(string.Empty));
if (type.IsValueType || // type has a parameterless ctor
type.GetConstructor(Type.EmptyTypes) != null)
return Expression.Lambda<Func<dynamic>>(Expression.New(type));
var info = typeof(FormatterServices).GetMethod("GetUninitializedObject");
var call = Expression.Call(info, Expression.Constant(type));
return call;
//return Expression.Lambda<Func<dynamic>>(call);
}
private IEnumerable<PropertyToFieldMapper> MakeWriters(Type type) {
var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
var fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
var list = (from field in fields
let property = properties.FirstOrDefault(prop => NamingConvention(field, prop))
where property != null
select new PropertyToFieldMapper(field, property)).ToList();
foreach (var item in list) {
var sourceParameter = Expression.Parameter(type, "sourceParameter");
var propertyGetter = Expression.Property(sourceParameter, item.Property.Name);
var targetParameter = Expression.Parameter(type, "targetParameter");
var setterInfo = item.Field.GetType().GetMethod("SetValue", new[] { typeof(object), typeof(object) });
var setterCall = Expression.Call(Expression.Constant(item.Field), setterInfo,
new Expression[] {
Expression.Convert(targetParameter,typeof(object)),
Expression.Convert(propertyGetter,typeof(object))
});
var call = Expression.Lambda(setterCall, new[] { targetParameter, sourceParameter });
item.Call = call;
}
return list;
}
private Func<dynamic, dynamic> MakeCreator(
Type type, Expression ctor,
IEnumerable<PropertyToFieldMapper> writers) {
var list = new List<Expression>();
// creating new target
var targetVariable = Expression.Variable(type, "targetVariable");
list.Add(Expression.Assign(targetVariable, Expression.Convert(ctor, type)));
// find all properties in incoming data
var sourceParameter = Expression.Parameter(typeof(object), "sourceParameter");
var sourceTypeVariable = Expression.Variable(typeof(Type));
var sourceTypeGetter = Expression.Call(sourceParameter, "GetType", Type.EmptyTypes);
list.Add(Expression.Assign(sourceTypeVariable, sourceTypeGetter));
var sourcePropertiesVariable = Expression.Variable(typeof(PropertyInfo[]));
var sourcePropertiesGetter = Expression.Call(sourceTypeVariable, "GetProperties", Type.EmptyTypes);
list.Add(Expression.Assign(sourcePropertiesVariable, sourcePropertiesGetter));
// itrate over writers and add their Call to block
foreach (var writer in writers) {
var param = Expression.Parameter(typeof(PropertyInfo));
var prop = Expression.Property(param, "Name");
var eq = Expression.Equal(Expression.Constant(writer.Property.Name), prop);
var any = CallAny.Call(sourcePropertiesVariable, Expression.Lambda(eq, param));
var predicate = Expression.IfThen(any,
Expression.Lambda(writer.Call, new[] { targetVariable, sourceParameter }));
list.Add(predicate);
}
list.Add(targetVariable);
var block = Expression.Block(new[] { targetVariable, sourceTypeVariable, sourcePropertiesVariable }, list);
var lambda = Expression.Lambda<Func<dynamic, dynamic>>(
block, new[] { sourceParameter }
);
return lambda.Compile();
}
public dynamic Create(dynamic data) {
return _creator.Invoke(data);
}
private class PropertyToFieldMapper {
private readonly FieldInfo _field;
private readonly PropertyInfo _property;
public PropertyToFieldMapper(FieldInfo field, PropertyInfo property) {
_field = field;
_property = property;
}
public FieldInfo Field {
get { return _field; }
}
public PropertyInfo Property {
get { return _property; }
}
public Expression Call { get; set; }
}
}
Also, I have this CallAny class, created from here.
public class CallAny {
public static Expression Call(Expression collection, Expression predicate) {
Type cType = GetIEnumerableImpl(collection.Type);
collection = Expression.Convert(collection, cType);
Type elemType = cType.GetGenericArguments()[0];
Type predType = typeof(Func<,>).MakeGenericType(elemType, typeof(bool));
// Enumerable.Any<T>(IEnumerable<T>, Func<T,bool>)
var anyMethod = (MethodInfo)
GetGenericMethod(typeof(Enumerable), "Any", new[] { elemType },
new[] { cType, predType }, BindingFlags.Static);
return Expression.Call(anyMethod, collection, predicate);
}
static MethodBase GetGenericMethod(Type type, string name, Type[] typeArgs, Type[] argTypes, BindingFlags flags) {
int typeArity = typeArgs.Length;
var methods = type.GetMethods()
.Where(m => m.Name == name)
.Where(m => m.GetGenericArguments().Length == typeArity)
.Select(m => m.MakeGenericMethod(typeArgs));
return Type.DefaultBinder.SelectMethod(flags, methods.ToArray(), argTypes, null);
}
static Type GetIEnumerableImpl(Type type) {
// Get IEnumerable implementation. Either type is IEnumerable<T> for some T,
// or it implements IEnumerable<T> for some T. We need to find the interface.
if (IsIEnumerable(type))
return type;
Type[] t = type.FindInterfaces((m, o) => IsIEnumerable(m), null);
Debug.Assert(t.Length == 1);
return t[0];
}
static bool IsIEnumerable(Type type) {
return type.IsGenericType
&& type.GetGenericTypeDefinition() == typeof(IEnumerable<>);
}
}
And here is usage:
var inst = new InstanceCreator(typeof (Model)).Create(new {MyData});
Well, I found the problem. I should use ExpandoObject instead of dynamic keyword. And pass it to logic as IDictionary<string, object>. Here is the solution:
public class InstanceCreator {
static public readonly Func<FieldInfo, PropertyInfo, bool> NamingConvention;
static InstanceCreator() {
NamingConvention = (f, p) => {
var startsWithUnderscope = f.Name.StartsWith("_");
var hasSameName = p.Name.Equals(f.Name.Remove(0, 1), StringComparison.OrdinalIgnoreCase);
var hasSameType = f.FieldType == p.PropertyType;
return startsWithUnderscope && hasSameName && hasSameType &&
f.IsInitOnly && !p.CanWrite;
};
}
private readonly Type _type;
private readonly Func<IDictionary<string, object>, dynamic> _creator;
public InstanceCreator(Type type) {
_type = type;
var ctor = GetCtor(type);
var propertyToFieldMappers = MakeMappers(type);
_creator = MakeCreator(type, ctor, propertyToFieldMappers);
}
private Expression GetCtor(Type type) {
if (type == typeof(string)) // ctor for string
return Expression.Lambda<Func<dynamic>>(
Expression.Constant(string.Empty));
if (type.IsValueType || // type has a parameterless ctor
type.GetConstructor(Type.EmptyTypes) != null)
return Expression.Lambda<Func<dynamic>>(Expression.New(type));
var info = typeof(FormatterServices).GetMethod("GetUninitializedObject");
return Expression.Call(info, Expression.Constant(type));
}
private IEnumerable<PropertyToFieldMapper> MakeMappers(Type type) {
var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
var fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
var list = from field in fields
let property = properties.FirstOrDefault(prop => NamingConvention(field, prop))
where property != null
select new PropertyToFieldMapper(field, property);
return list;
}
private Func<IDictionary<string, object>, dynamic> MakeCreator(
Type type, Expression ctor,
IEnumerable<PropertyToFieldMapper> maps) {
var list = new List<Expression>();
var vList = new List<ParameterExpression>();
// creating new target
var targetVariable = Expression.Variable(type, "targetVariable");
vList.Add(targetVariable);
list.Add(Expression.Assign(targetVariable, Expression.Convert(ctor, type)));
// accessing source
var sourceType = typeof(IDictionary<string, object>);
var sourceParameter = Expression.Parameter(sourceType, "sourceParameter");
// calling source ContainsKey(string) method
var containsKeyMethodInfo = sourceType.GetMethod("ContainsKey", new[] { typeof(string) });
var accessSourceIndexerProp = sourceType.GetProperty("Item");
var accessSourceIndexerInfo = accessSourceIndexerProp.GetGetMethod();
// itrate over writers and add their Call to block
var containsKeyMethodArgument = Expression.Variable(typeof(string), "containsKeyMethodArgument");
vList.Add(containsKeyMethodArgument);
foreach (var map in maps) {
list.Add(Expression.Assign(containsKeyMethodArgument, Expression.Constant(map.Property.Name)));
var containsKeyMethodCall = Expression.Call(sourceParameter, containsKeyMethodInfo,
new Expression[] { containsKeyMethodArgument });
// creating writer
var sourceValue = Expression.Call(sourceParameter, accessSourceIndexerInfo,
new Expression[] { containsKeyMethodArgument });
var setterInfo = map.Field.GetType().GetMethod("SetValue", new[] { typeof(object), typeof(object) });
var setterCall = Expression.Call(Expression.Constant(map.Field), setterInfo,
new Expression[] {
Expression.Convert(targetVariable,typeof(object)),
Expression.Convert(sourceValue,typeof(object))
});
list.Add(Expression.IfThen(containsKeyMethodCall, setterCall));
}
list.Add(targetVariable);
var block = Expression.Block(vList, list);
var lambda = Expression.Lambda<Func<IDictionary<string, object>, dynamic>>(
block, new[] { sourceParameter }
);
return lambda.Compile();
}
public dynamic Create(IDictionary<string, object> data) {
return _creator.Invoke(data);
}
private class PropertyToFieldMapper {
private readonly FieldInfo _field;
private readonly PropertyInfo _property;
public PropertyToFieldMapper(FieldInfo field, PropertyInfo property) {
_field = field;
_property = property;
}
public FieldInfo Field {
get { return _field; }
}
public PropertyInfo Property {
get { return _property; }
}
}
}

Convert Dictionary<string, object> To Anonymous Object?

First, and to make things clearer I'll explain my scenario from the top:
I have a method which has the following signature:
public virtual void SendEmail(String from, List<String> recepients, Object model)
What I want to do is generate an anonymous object which has the properties of the model object along with the first two parameters as well. Flattening the model object into a PropertyInfo[] is very straightforward. Accordingly, I thought of creating a Dictionary which would hold the PropertyInfo's and the first two params, and then be converted into the anonymous object where the key is the name of the property and the value is the actual value of the property.
Is that possible? Any other suggestions?
If you really want to convert the dictionary to an object that has the items 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;
I tried to do this in one statement with a 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); return a; });
string value = eo.Property;
If you want to convert Dictionary<string, object> To 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 obtain your object.
Where AnonymousType class code is:
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;
}
}
Reference: https://stackoverflow.com/a/29428640/2073920
If you have a class you want to covert the dictionary too, you can use the following to convert a dictionary to an object of that class:
Example class:
public class Properties1
{
public string Property { get; set; }
}
The solution:
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 could also use a method like this to build the object from the dictionary, obviously this also requires you to have a class.
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 the class you can create a dynamic object from a dictionary like this:
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;
Slightly more modular version of svick's answer, using a couple 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;
}
}
The code below handles sub-dictionaries and converts them to nested dynamic objects as well:
[return: NotNullIfNotNull(nameof(dictionary))]
static dynamic? ToDynamic(IReadOnlyDictionary<string, object?>? dictionary) =>
dictionary?.Aggregate(
(IDictionary<string, object?>)new ExpandoObject(),
(obj, i) =>
{
if (i.Value is IReadOnlyDictionary<string, object?> nestedDictionary)
obj.Add(new(i.Key, ToDynamic(nestedDictionary)));
else
obj.Add(i);
return obj;
});
This approach allows you to access the contents of nested dictionaries just by accessing the dynamic object itself:
var record = ToDynamic(...);
string cityName = record.city.name;
Anonymous objects are one that generated for you by compiler. You cannot generate dynamically create one. On the other hand you can emit such object, but I really do not think this is good idea.
May be you can try dynamic objects? The result will be an object with all properties you need.
The credit here goes to the accepted answer. Adding this because I wanted to turn a List< Dictionary< string,object >> into a List< dynamic>. The purpose is for pulling records from a 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;
}

Categories

Resources