forked from ThatRendle/Simple.Data
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathObjectEx.cs
More file actions
73 lines (59 loc) · 2.88 KB
/
ObjectEx.cs
File metadata and controls
73 lines (59 loc) · 2.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Simple.Data.Extensions
{
using System.Collections.Concurrent;
using System.Linq.Expressions;
using System.Reflection;
public static class ObjectEx
{
private static readonly ConcurrentDictionary<Type, Func<object, IDictionary<string, object>>> Converters =
new ConcurrentDictionary<Type, Func<object, IDictionary<string, object>>>();
public static IDictionary<string, object> AnonymousObjectToDictionary(this object obj)
{
return obj.GetType().GetProperties().ToDictionary(p => p.Name, p => p.GetValue(obj, null));
}
public static IDictionary<string, object> ObjectToDictionary(this object obj)
{
if (obj == null) return new Dictionary<string, object>();
var alreadyADictionary = obj as IDictionary<string,object>;
if (alreadyADictionary != null)
{
return new Dictionary<string, object>(alreadyADictionary);
}
return Converters.GetOrAdd(obj.GetType(), MakeToDictionaryFunc)(obj);
}
private static Func<object, IDictionary<string, object>> MakeToDictionaryFunc(Type type)
{
var param = Expression.Parameter(typeof(object));
var typed = Expression.Variable(type);
var newDict = Expression.New(typeof(Dictionary<string, object>));
var elementInitsForType = GetElementInitsForType(type, typed);
var listInit = Expression.ListInit(newDict, elementInitsForType);
var block = Expression.Block(new[] { typed },
Expression.Assign(typed, Expression.Convert(param, type)),
listInit);
return Expression.Lambda<Func<object, IDictionary<String, object>>>(block, param).Compile();
}
static readonly MethodInfo DictionaryAddMethod = typeof(Dictionary<string, object>).GetMethod("Add");
static IEnumerable<ElementInit> GetElementInitsForType(Type type, Expression param)
{
return type.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(p => p.CanRead)
.Select(p => PropertyToElementInit(p, param));
}
static ElementInit PropertyToElementInit(PropertyInfo propertyInfo, Expression instance)
{
return Expression.ElementInit(DictionaryAddMethod,
Expression.Constant(propertyInfo.Name),
Expression.Convert(Expression.Property(instance, propertyInfo), typeof(object)));
}
internal static bool IsAnonymous(this object obj)
{
if (obj == null) return false;
return obj.GetType().Namespace == null;
}
}
}