Skip to content

Commit

Permalink
Remove the need for JIT in ReflectionUtil
Browse files Browse the repository at this point in the history
Based on @zhangzhibin 's contribution  f8537cb
Tuned the unit tests so they expect the appropriate exception and pass.
  • Loading branch information
Quentin Brandon committed Sep 7, 2016
1 parent 2353fca commit 985243b
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 22 deletions.
4 changes: 2 additions & 2 deletions src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ public void SetValue_SingleFields_WrongType()
{
IMessage message = SampleMessages.CreateFullTestAllTypes();
var fields = message.Descriptor.Fields;
Assert.Throws<InvalidCastException>(() => fields[TestAllTypes.SingleBoolFieldNumber].Accessor.SetValue(message, "This isn't a bool"));
Assert.Throws<ArgumentException>(() => fields[TestAllTypes.SingleBoolFieldNumber].Accessor.SetValue(message, "This isn't a bool"));
}

[Test]
Expand All @@ -175,7 +175,7 @@ public void GetValue_IncorrectType()
{
IMessage message = SampleMessages.CreateFullTestAllTypes();
var fields = message.Descriptor.Fields;
Assert.Throws<InvalidCastException>(() => fields[TestAllTypes.SingleBoolFieldNumber].Accessor.GetValue(new TestMap()));
Assert.Throws<System.Reflection.TargetException>(() => fields[TestAllTypes.SingleBoolFieldNumber].Accessor.GetValue(new TestMap()));
}

[Test]
Expand Down
40 changes: 20 additions & 20 deletions src/Google.Protobuf/Reflection/ReflectionUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
namespace Google.Protobuf.Reflection
{
/// <summary>
/// In order to run on iOS (no JIT) we had to use Invoke which results in a bit
/// of a performance cost. The original description is as follows:
/// The methods in this class are somewhat evil, and should not be tampered with lightly.
/// Basically they allow the creation of relatively weakly typed delegates from MethodInfos
/// which are more strongly typed. They do this by creating an appropriate strongly typed
Expand All @@ -58,11 +60,11 @@ internal static class ReflectionUtil
/// </summary>
internal static Func<IMessage, object> CreateFuncIMessageObject(MethodInfo method)
{
ParameterExpression parameter = Expression.Parameter(typeof(IMessage), "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<IMessage, object>>(upcast, parameter).Compile();
return (IMessage message) =>
{
var returnValue = method.Invoke(message, null) as object;
return returnValue;
};
}

/// <summary>
Expand All @@ -71,11 +73,11 @@ internal static Func<IMessage, object> CreateFuncIMessageObject(MethodInfo metho
/// </summary>
internal static Func<IMessage, T> CreateFuncIMessageT<T>(MethodInfo method)
{
ParameterExpression parameter = Expression.Parameter(typeof(IMessage), "p");
Expression downcast = Expression.Convert(parameter, method.DeclaringType);
Expression call = Expression.Call(downcast, method);
Expression upcast = Expression.Convert(call, typeof(T));
return Expression.Lambda<Func<IMessage, T>>(upcast, parameter).Compile();
return (IMessage message) =>
{
var returnValue = (T)method.Invoke(message, null);
return returnValue;
};
}

/// <summary>
Expand All @@ -84,12 +86,10 @@ internal static Func<IMessage, T> CreateFuncIMessageT<T>(MethodInfo method)
/// </summary>
internal static Action<IMessage, object> CreateActionIMessageObject(MethodInfo method)
{
ParameterExpression targetParameter = Expression.Parameter(typeof(IMessage), "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<IMessage, object>>(call, targetParameter, argParameter).Compile();
return (IMessage arg1, object arg2) =>
{
method.Invoke(arg1, new object[]{ arg2 });
};
}

/// <summary>
Expand All @@ -98,10 +98,10 @@ internal static Action<IMessage, object> CreateActionIMessageObject(MethodInfo m
/// </summary>
internal static Action<IMessage> CreateActionIMessage(MethodInfo method)
{
ParameterExpression targetParameter = Expression.Parameter(typeof(IMessage), "target");
Expression castTarget = Expression.Convert(targetParameter, method.DeclaringType);
Expression call = Expression.Call(castTarget, method);
return Expression.Lambda<Action<IMessage>>(call, targetParameter).Compile();
return (IMessage obj) =>
{
method.Invoke(obj, null);
};
}
}
}

0 comments on commit 985243b

Please sign in to comment.