-
Notifications
You must be signed in to change notification settings - Fork 2k
/
FieldUtils.cs
105 lines (92 loc) · 3.99 KB
/
FieldUtils.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
using System;
using System.Reflection;
using System.Reflection.Emit;
namespace Orleans.Serialization
{
public class FieldUtils : IFieldUtils
{
/// <inheritdoc />
public Delegate GetGetter(FieldInfo field)
{
return GetGetDelegate(
field,
typeof(Func<,>).MakeGenericType(field.DeclaringType, field.FieldType),
new[] { field.DeclaringType });
}
/// <summary>
/// Returns a delegate to get the value of a specified field.
/// </summary>
/// <param name="field">
/// The field.
/// </param>
/// <param name="delegateType">The delegate type.</param>
/// <param name="parameterTypes">The parameter types.</param>
/// <returns>A delegate to get the value of a specified field.</returns>
private static Delegate GetGetDelegate(FieldInfo field, Type delegateType, Type[] parameterTypes)
{
var declaringType = field.DeclaringType;
if (declaringType == null)
{
throw new InvalidOperationException("Field " + field.Name + " does not have a declaring type.");
}
// Create a method to hold the generated IL.
var method = new DynamicMethod(
field.Name + "Get",
field.FieldType,
parameterTypes,
typeof(FieldUtils).Module,
true);
// Emit IL to return the value of the Transaction property.
var emitter = method.GetILGenerator();
emitter.Emit(OpCodes.Ldarg_0);
emitter.Emit(OpCodes.Ldfld, field);
emitter.Emit(OpCodes.Ret);
return method.CreateDelegate(delegateType);
}
/// <inheritdoc />
public Delegate GetReferenceSetter(FieldInfo field)
{
var delegateType = typeof(Action<,>).MakeGenericType(field.DeclaringType, field.FieldType);
return GetSetDelegate(field, delegateType, new[] { field.DeclaringType, field.FieldType });
}
/// <inheritdoc />
public Delegate GetValueSetter(FieldInfo field)
{
var declaringType = field.DeclaringType;
if (declaringType == null)
{
throw new InvalidOperationException("Field " + field.Name + " does not have a declaring type.");
}
// Value types need to be passed by-ref.
var parameterTypes = new[] { declaringType.MakeByRefType(), field.FieldType };
var delegateType = typeof(ValueTypeSetter<,>).MakeGenericType(field.DeclaringType, field.FieldType);
return GetSetDelegate(field, delegateType, parameterTypes);
}
/// <summary>
/// Returns a delegate to set the value of a specified field.
/// </summary>
/// <param name="field">
/// The field.
/// </param>
/// <param name="delegateType">The delegate type.</param>
/// <param name="parameterTypes">The parameter types.</param>
/// <returns>A delegate to set the value of a specified field.</returns>
private static Delegate GetSetDelegate(FieldInfo field, Type delegateType, Type[] parameterTypes)
{
var declaringType = field.DeclaringType;
if (declaringType == null)
{
throw new InvalidOperationException("Field " + field.Name + " does not have a declaring type.");
}
// Create a method to hold the generated IL.
var method = new DynamicMethod(field.Name + "Set", null, parameterTypes, typeof(FieldUtils).Module, true);
// Emit IL to return the value of the Transaction property.
var emitter = method.GetILGenerator();
emitter.Emit(OpCodes.Ldarg_0);
emitter.Emit(OpCodes.Ldarg_1);
emitter.Emit(OpCodes.Stfld, field);
emitter.Emit(OpCodes.Ret);
return method.CreateDelegate(delegateType);
}
}
}