-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMemberAccessor.cs
More file actions
86 lines (74 loc) · 3.56 KB
/
MemberAccessor.cs
File metadata and controls
86 lines (74 loc) · 3.56 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
74
75
76
77
78
79
80
81
82
83
84
85
86
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
namespace Glide
{
internal class MemberAccessor
{
public object Target { get; private set; }
public string MemberName { get; private set; }
public Type MemberType { get; private set; }
public object Value
{
get { return getMethod(Target); }
set { setMethod(Target, value); }
}
public MemberAccessor(object target, string name, bool writeRequired = true)
{
var T = target.GetType();
PropertyInfo propInfo = null;
FieldInfo fieldInfo = null;
Target = target;
if ((propInfo = T.GetProperty(name, flags)) != null)
{
MemberType = propInfo.PropertyType;
MemberName = propInfo.Name;
{
var param = Expression.Parameter(typeof(object));
var instance = Expression.Convert(param, propInfo.DeclaringType);
var convert = Expression.TypeAs(Expression.Property(instance, propInfo), typeof(object));
getMethod = Expression.Lambda<Func<object, object>>(convert, param).Compile();
}
if (writeRequired)
{
var param = Expression.Parameter(typeof(object));
var argument = Expression.Parameter(typeof(object));
var setterCall = Expression.Call(
Expression.Convert(param, propInfo.DeclaringType),
propInfo.GetSetMethod(),
Expression.Convert(argument, propInfo.PropertyType));
setMethod = Expression.Lambda<Action<object, object>>(setterCall, param, argument).Compile();
}
}
else if ((fieldInfo = T.GetField(name, flags)) != null)
{
MemberType = fieldInfo.FieldType;
MemberName = fieldInfo.Name;
{
var self = Expression.Parameter(typeof(object));
var instance = Expression.Convert(self, fieldInfo.DeclaringType);
var field = Expression.Field(instance, fieldInfo);
var convert = Expression.TypeAs(field, typeof(object));
getMethod = Expression.Lambda<Func<object, object>>(convert, self).Compile();
}
{
var self = Expression.Parameter(typeof(object));
var value = Expression.Parameter(typeof(object));
var fieldExp = Expression.Field(Expression.Convert(self, fieldInfo.DeclaringType), fieldInfo);
var assignExp = Expression.Assign(fieldExp, Expression.Convert(value, fieldInfo.FieldType));
setMethod = Expression.Lambda<Action<object, object>>(assignExp, self, value).Compile();
}
}
else
{
throw new Exception(string.Format("Field or {0} property '{1}' not found on object of type {2}.",
writeRequired ? "read/write" : "readable",
name, T.FullName));
}
}
protected Func<object, object> getMethod;
protected Action<object, object> setMethod;
private static BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
}
}