forked from ServiceStack/ServiceStack
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDelegateFactory.cs
More file actions
71 lines (53 loc) · 2.56 KB
/
DelegateFactory.cs
File metadata and controls
71 lines (53 loc) · 2.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
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace ServiceStack.Reflection
{
public static class DelegateFactory
{
/*
* MethodInfo method = typeof(String).GetMethod("StartsWith", new[] { typeof(string) });
LateBoundMethod callback = DelegateFactory.Create(method);
string foo = "this is a test";
bool result = (bool) callback(foo, new[] { "this" });
result.ShouldBeTrue();
*/
public delegate object LateBoundMethod(object target, object[] arguments);
public static LateBoundMethod Create(MethodInfo method)
{
ParameterExpression instanceParameter = Expression.Parameter(typeof(object), "target");
ParameterExpression argumentsParameter = Expression.Parameter(typeof(object[]), "arguments");
MethodCallExpression call = Expression.Call(
Expression.Convert(instanceParameter, method.DeclaringType),
method,
CreateParameterExpressions(method, argumentsParameter));
Expression<LateBoundMethod> lambda = Expression.Lambda<LateBoundMethod>(
Expression.Convert(call, typeof(object)),
instanceParameter,
argumentsParameter);
return lambda.Compile();
}
private static Expression[] CreateParameterExpressions(MethodInfo method, Expression argumentsParameter)
{
return method.GetParameters().Select((parameter, index) =>
Expression.Convert(
Expression.ArrayIndex(argumentsParameter, Expression.Constant(index)),
parameter.ParameterType)).ToArray();
}
public delegate void LateBoundVoid(object target, object[] arguments);
public static LateBoundVoid CreateVoid(MethodInfo method)
{
ParameterExpression instanceParameter = Expression.Parameter(typeof(object), "target");
ParameterExpression argumentsParameter = Expression.Parameter(typeof(object[]), "arguments");
MethodCallExpression call = Expression.Call(
Expression.Convert(instanceParameter, method.DeclaringType),
method,
CreateParameterExpressions(method, argumentsParameter));
var lambda = Expression.Lambda<LateBoundVoid>(
Expression.Convert(call, method.ReturnParameter.ParameterType),
instanceParameter,
argumentsParameter);
return lambda.Compile();
}
}
}