aboutsummaryrefslogtreecommitdiff
path: root/csharp/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs
diff options
context:
space:
mode:
Diffstat (limited to 'csharp/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs')
-rw-r--r--csharp/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs110
1 files changed, 26 insertions, 84 deletions
diff --git a/csharp/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs b/csharp/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs
index 29399b0c..d3053920 100644
--- a/csharp/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs
+++ b/csharp/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs
@@ -31,6 +31,7 @@
#endregion
using System;
+using System.Linq.Expressions;
using System.Reflection;
namespace Google.Protobuf.FieldAccess
@@ -51,101 +52,42 @@ namespace Google.Protobuf.FieldAccess
internal static readonly Type[] EmptyTypes = new Type[0];
/// <summary>
- /// Creates a delegate which will execute the given method and then return
- /// the result as an object.
+ /// Creates a delegate which will cast the argument to the appropriate method target type,
+ /// call the method on it, then convert the result to object.
/// </summary>
- public static Func<T, object> CreateUpcastDelegate<T>(MethodInfo method)
+ internal static Func<object, object> CreateFuncObjectObject(MethodInfo method)
{
- // The tricky bit is invoking CreateCreateUpcastDelegateImpl with the right type parameters
- MethodInfo openImpl = typeof(ReflectionUtil).GetMethod("CreateUpcastDelegateImpl");
- MethodInfo closedImpl = openImpl.MakeGenericMethod(typeof(T), method.ReturnType);
- return (Func<T, object>) closedImpl.Invoke(null, new object[] {method});
+ ParameterExpression parameter = Expression.Parameter(typeof(object), "p");
+ Expression downcast = Expression.Convert(parameter, method.DeclaringType);
+ Expression call = Expression.Call(downcast, method);
+ Expression upcast = Expression.Convert(call, typeof(object));
+ return Expression.Lambda<Func<object, object>>(upcast, parameter).Compile();
}
-
+
/// <summary>
- /// Method used solely for implementing CreateUpcastDelegate. Public to avoid trust issues
- /// in low-trust scenarios.
+ /// Creates a delegate which will execute the given method after casting the first argument to
+ /// the target type of the method, and the second argument to the first parameter type of the method.
/// </summary>
- public static Func<TSource, object> CreateUpcastDelegateImpl<TSource, TResult>(MethodInfo method)
+ internal static Action<object, object> CreateActionObjectObject(MethodInfo method)
{
- // Convert the reflection call into an open delegate, i.e. instead of calling x.Method()
- // we'll call getter(x).
- Func<TSource, TResult> getter = ReflectionUtil.CreateDelegateFunc<TSource, TResult>(method);
-
- // Implicit upcast to object (within the delegate)
- return source => getter(source);
+ ParameterExpression targetParameter = Expression.Parameter(typeof(object), "target");
+ ParameterExpression argParameter = Expression.Parameter(typeof(object), "arg");
+ Expression castTarget = Expression.Convert(targetParameter, method.DeclaringType);
+ Expression castArgument = Expression.Convert(argParameter, method.GetParameters()[0].ParameterType);
+ Expression call = Expression.Call(castTarget, method, castArgument);
+ return Expression.Lambda<Action<object, object>>(call, targetParameter, argParameter).Compile();
}
/// <summary>
- /// Creates a delegate which will execute the given method after casting the parameter
- /// down from object to the required parameter type.
+ /// Creates a delegate which will execute the given method after casting the first argument to
+ /// the target type of the method.
/// </summary>
- public static Action<T, object> CreateDowncastDelegate<T>(MethodInfo method)
- {
- MethodInfo openImpl = typeof(ReflectionUtil).GetMethod("CreateDowncastDelegateImpl");
- MethodInfo closedImpl = openImpl.MakeGenericMethod(typeof(T), method.GetParameters()[0].ParameterType);
- return (Action<T, object>) closedImpl.Invoke(null, new object[] {method});
- }
-
- public static Action<TSource, object> CreateDowncastDelegateImpl<TSource, TParam>(MethodInfo method)
- {
- // Convert the reflection call into an open delegate, i.e. instead of calling x.Method(y) we'll
- // call Method(x, y)
- Action<TSource, TParam> call = ReflectionUtil.CreateDelegateAction<TSource, TParam>(method);
-
- return (source, parameter) => call(source, (TParam) parameter);
- }
-
- /// <summary>
- /// Creates a delegate which will execute the given method after casting the parameter
- /// down from object to the required parameter type.
- /// </summary>
- public static Action<T, object> CreateDowncastDelegateIgnoringReturn<T>(MethodInfo method)
- {
- MethodInfo openImpl = typeof(ReflectionUtil).GetMethod("CreateDowncastDelegateIgnoringReturnImpl");
- MethodInfo closedImpl = openImpl.MakeGenericMethod(typeof(T), method.GetParameters()[0].ParameterType,
- method.ReturnType);
- return (Action<T, object>) closedImpl.Invoke(null, new object[] {method});
- }
-
- public static Action<TSource, object> CreateDowncastDelegateIgnoringReturnImpl<TSource, TParam, TReturn>(
- MethodInfo method)
- {
- // Convert the reflection call into an open delegate, i.e. instead of calling x.Method(y) we'll
- // call Method(x, y)
- Func<TSource, TParam, TReturn> call = ReflectionUtil.CreateDelegateFunc<TSource, TParam, TReturn>(method);
-
- return delegate(TSource source, object parameter) { call(source, (TParam) parameter); };
- }
-
- internal static Func<TResult> CreateDelegateFunc<TResult>(MethodInfo method)
- {
- object tdelegate = Delegate.CreateDelegate(typeof(Func<TResult>), null, method);
- return (Func<TResult>)tdelegate;
- }
-
- internal static Func<T, TResult> CreateDelegateFunc<T, TResult>(MethodInfo method)
- {
- object tdelegate = Delegate.CreateDelegate(typeof(Func<T, TResult>), null, method);
- return (Func<T, TResult>)tdelegate;
- }
-
- internal static Func<T1, T2, TResult> CreateDelegateFunc<T1, T2, TResult>(MethodInfo method)
- {
- object tdelegate = Delegate.CreateDelegate(typeof(Func<T1, T2, TResult>), null, method);
- return (Func<T1, T2, TResult>)tdelegate;
- }
-
- internal static Action<T> CreateDelegateAction<T>(MethodInfo method)
- {
- object tdelegate = Delegate.CreateDelegate(typeof(Action<T>), null, method);
- return (Action<T>)tdelegate;
- }
-
- internal static Action<T1, T2> CreateDelegateAction<T1, T2>(MethodInfo method)
+ internal static Action<object> CreateActionObject(MethodInfo method)
{
- object tdelegate = Delegate.CreateDelegate(typeof(Action<T1, T2>), null, method);
- return (Action<T1, T2>)tdelegate;
+ ParameterExpression targetParameter = Expression.Parameter(typeof(object), "target");
+ Expression castTarget = Expression.Convert(targetParameter, method.DeclaringType);
+ Expression call = Expression.Call(castTarget, method);
+ return Expression.Lambda<Action<object>>(call, targetParameter).Compile();
}
}
} \ No newline at end of file