-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathPropertyReferenceBase.cs
122 lines (100 loc) · 3.64 KB
/
PropertyReferenceBase.cs
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
using System;
using System.Reflection;
#if CAN_USE_EXPR_TREE
using System.Linq.Expressions;
#endif
namespace TypeInspector
{
/// <summary>
/// Abstract class for make property referencies in editor
/// </summary>
public abstract class PropertyReferenceBase
{
protected PropertyInfo _propertyCache;
public abstract Type GetSourceType();
public abstract PropertyInfo GetProperty();
#if CAN_USE_EXPR_TREE
private Action<object, object> setterDelegate;
private Func<object, object> getterDelegate;
#endif
/// <summary>
/// Setup value to target property
/// </summary>
/// <param name="instance"> instance where is target property </param>
/// <param name="data"> value which will set to target property </param>
public void Set(object instance, object data)
{
Init();
#if CAN_USE_EXPR_TREE
setterDelegate(instance, data);
return;
#endif
var property = GetProperty();
if (property == null)
{
return;
}
property.SetValue(instance, data);
}
/// <summary>
/// Get current value from target property from 'instance' object
/// </summary>
/// <param name="instance"> insatnce of target object which contain target propetry </param>
/// <returns></returns>
public object Get(object instance)
{
Init();
#if CAN_USE_EXPR_TREE
return getterDelegate(instance);
#endif
return GetProperty()?.GetValue(instance);
}
/// <summary>
/// Make initialization
/// </summary>
public void Init()
{
#if CAN_USE_EXPR_TREE
if (setterDelegate != null && getterDelegate != null)
{
return;
}
if (!IsValid())
{
return;
}
var property = GetProperty();
getterDelegate = GetValueGetter<object>(property);
setterDelegate = GetValueSetter<object>(property);
#endif
}
/// <summary>
/// Return information about property operations is available
/// </summary>
/// <returns> true if all is ok </returns>
public bool IsValid()
{
return GetProperty() != null;
}
#if CAN_USE_EXPR_TREE
public static Func<T, object> GetValueGetter<T>(PropertyInfo propertyInfo)
{
var instance = Expression.Parameter(typeof(object), "i");
var property = Expression.Property(Expression.TypeAs(instance, propertyInfo.DeclaringType), propertyInfo);
var convert = Expression.TypeAs(property, typeof(object));
return (Func<T, object>)Expression.Lambda(convert, instance).Compile();
}
public static Action<T, object> GetValueSetter<T>(PropertyInfo propertyInfo)
{
var instance = Expression.Parameter(typeof(object), "i");
var property = Expression.TypeAs(instance, propertyInfo.DeclaringType);
var argument = Expression.Parameter(typeof(object), "a");
var setterCall = Expression.Call(
property,
propertyInfo.GetSetMethod(),
Expression.Convert(argument, propertyInfo.PropertyType));
return (Action<T, object>)Expression.Lambda(setterCall, instance, argument).Compile();
}
#endif
}
}