Fix and tests for invoking static methods
This commit is contained in:
parent
871072d9c3
commit
b2ec59a3f3
@ -12,12 +12,19 @@ namespace Tapeti.Tests.Config
|
||||
public void RegisterController()
|
||||
{
|
||||
var bindings = GetControllerBindings<TestController>();
|
||||
bindings.Should().HaveCount(1);
|
||||
bindings.Should().HaveCount(2);
|
||||
|
||||
var handleSimpleMessageBinding = bindings.Single(b => b is IControllerMethodBinding cmb &&
|
||||
cmb.Controller == typeof(TestController) &&
|
||||
cmb.Method.Name == "HandleSimpleMessage");
|
||||
handleSimpleMessageBinding.QueueType.Should().Be(QueueType.Dynamic);
|
||||
|
||||
|
||||
var handleSimpleMessageStaticBinding = bindings.Single(b => b is IControllerMethodBinding cmb &&
|
||||
cmb.Controller == typeof(TestController) &&
|
||||
cmb.Method.Name == "HandleSimpleMessageStatic");
|
||||
handleSimpleMessageStaticBinding.QueueType.Should().Be(QueueType.Dynamic);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -35,6 +42,10 @@ namespace Tapeti.Tests.Config
|
||||
public void HandleSimpleMessage(TestMessage message)
|
||||
{
|
||||
}
|
||||
|
||||
public static void HandleSimpleMessageStatic(TestMessage message)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore
|
||||
|
227
Tapeti.Tests/Helpers/ExpressionInvokerTest.cs
Normal file
227
Tapeti.Tests/Helpers/ExpressionInvokerTest.cs
Normal file
@ -0,0 +1,227 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using FluentAssertions;
|
||||
using Tapeti.Helpers;
|
||||
using Xunit;
|
||||
|
||||
namespace Tapeti.Tests.Helpers
|
||||
{
|
||||
public class ExpressionInvokerTest
|
||||
{
|
||||
[Fact]
|
||||
public void InstanceMethodVoidNoParameters()
|
||||
{
|
||||
const string methodName = nameof(InvokeTarget.InstanceMethodVoidNoParameters);
|
||||
var invoker = InvokerFor(methodName);
|
||||
|
||||
var target = new InvokeTarget();
|
||||
invoker.Invoke(target);
|
||||
|
||||
target.Verify(methodName);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void InstanceMethodReturnValueNoParameters()
|
||||
{
|
||||
const string methodName = nameof(InvokeTarget.InstanceMethodReturnValueNoParameters);
|
||||
var invoker = InvokerFor(methodName);
|
||||
|
||||
var target = new InvokeTarget();
|
||||
var returnValue = invoker.Invoke(target);
|
||||
|
||||
target.Verify(methodName);
|
||||
returnValue.Should().Be("Hello world!");
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void InstanceMethodVoidParameters()
|
||||
{
|
||||
const string methodName = nameof(InvokeTarget.InstanceMethodVoidParameters);
|
||||
var invoker = InvokerFor(methodName);
|
||||
|
||||
var target = new InvokeTarget();
|
||||
invoker.Invoke(target, 42);
|
||||
|
||||
target.Verify(methodName, "42");
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void InstanceMethodReturnValueParameters()
|
||||
{
|
||||
const string methodName = nameof(InvokeTarget.InstanceMethodReturnValueParameters);
|
||||
var invoker = InvokerFor(methodName);
|
||||
|
||||
var target = new InvokeTarget();
|
||||
var returnValue = invoker.Invoke(target, new byte[] { 42, 69 });
|
||||
|
||||
target.Verify(methodName, "42,69");
|
||||
returnValue.Should().Be(true);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void StaticMethodVoidNoParameters()
|
||||
{
|
||||
InvokeTarget.ResetStatic();
|
||||
|
||||
const string methodName = nameof(InvokeTarget.StaticMethodVoidNoParameters);
|
||||
var invoker = InvokerFor(methodName);
|
||||
|
||||
invoker.Invoke(null);
|
||||
|
||||
InvokeTarget.VerifyStatic(methodName);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void StaticMethodReturnValueNoParameters()
|
||||
{
|
||||
InvokeTarget.ResetStatic();
|
||||
|
||||
const string methodName = nameof(InvokeTarget.StaticMethodReturnValueNoParameters);
|
||||
var invoker = InvokerFor(methodName);
|
||||
|
||||
var returnValue = invoker.Invoke(null);
|
||||
|
||||
InvokeTarget.VerifyStatic(methodName);
|
||||
returnValue.Should().Be("Hello world!");
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void StaticMethodVoidParameters()
|
||||
{
|
||||
InvokeTarget.ResetStatic();
|
||||
|
||||
const string methodName = nameof(InvokeTarget.StaticMethodVoidParameters);
|
||||
var invoker = InvokerFor(methodName);
|
||||
|
||||
invoker.Invoke(null, 42);
|
||||
|
||||
InvokeTarget.VerifyStatic(methodName, "42");
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void StaticMethodReturnValueParameters()
|
||||
{
|
||||
InvokeTarget.ResetStatic();
|
||||
|
||||
const string methodName = nameof(InvokeTarget.StaticMethodReturnValueParameters);
|
||||
var invoker = InvokerFor(methodName);
|
||||
|
||||
var returnValue = invoker.Invoke(null, new byte[] { 42, 69 });
|
||||
|
||||
InvokeTarget.VerifyStatic(methodName, "42,69");
|
||||
returnValue.Should().Be(true);
|
||||
}
|
||||
|
||||
|
||||
private static ExpressionInvoke InvokerFor(string invokeTargetMethodName)
|
||||
{
|
||||
var method = typeof(InvokeTarget).GetMethod(invokeTargetMethodName);
|
||||
return method!.CreateExpressionInvoke();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ReSharper disable ParameterHidesMember
|
||||
private class InvokeTarget
|
||||
{
|
||||
private static string? staticMethodName;
|
||||
private static string? staticParameters;
|
||||
|
||||
private string? methodName;
|
||||
private string? parameters;
|
||||
|
||||
|
||||
public void InstanceMethodVoidNoParameters()
|
||||
{
|
||||
MethodCalled();
|
||||
}
|
||||
|
||||
public string InstanceMethodReturnValueNoParameters()
|
||||
{
|
||||
MethodCalled();
|
||||
return "Hello world!";
|
||||
}
|
||||
|
||||
public void InstanceMethodVoidParameters(int answer)
|
||||
{
|
||||
MethodCalled(answer.ToString());
|
||||
}
|
||||
|
||||
public bool InstanceMethodReturnValueParameters(IEnumerable<byte> values)
|
||||
{
|
||||
MethodCalled(string.Join(',', values.Select(v => v.ToString())));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public static void StaticMethodVoidNoParameters()
|
||||
{
|
||||
StaticMethodCalled();
|
||||
}
|
||||
|
||||
public static string StaticMethodReturnValueNoParameters()
|
||||
{
|
||||
StaticMethodCalled();
|
||||
return "Hello world!";
|
||||
}
|
||||
|
||||
public static void StaticMethodVoidParameters(int answer)
|
||||
{
|
||||
StaticMethodCalled(answer.ToString());
|
||||
}
|
||||
|
||||
public static bool StaticMethodReturnValueParameters(IEnumerable<byte> values)
|
||||
{
|
||||
StaticMethodCalled(string.Join(',', values.Select(v => v.ToString())));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private void MethodCalled(string parameters = "", [CallerMemberName]string methodName = "")
|
||||
{
|
||||
this.methodName.Should().BeNull();
|
||||
this.methodName = methodName;
|
||||
this.parameters = parameters;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void ResetStatic()
|
||||
{
|
||||
staticMethodName = null;
|
||||
staticParameters = null;
|
||||
}
|
||||
|
||||
|
||||
private static void StaticMethodCalled(string parameters = "", [CallerMemberName] string methodName = "")
|
||||
{
|
||||
staticMethodName.Should().BeNull();
|
||||
staticMethodName = methodName;
|
||||
staticParameters = parameters;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void Verify(string methodName, string parameters = "")
|
||||
{
|
||||
this.methodName.Should().Be(methodName);
|
||||
this.parameters.Should().Be(parameters);
|
||||
}
|
||||
|
||||
|
||||
public static void VerifyStatic(string methodName, string parameters = "")
|
||||
{
|
||||
staticMethodName.Should().Be(methodName);
|
||||
staticParameters.Should().Be(parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -44,22 +44,25 @@ namespace Tapeti.Helpers
|
||||
.ToArray();
|
||||
|
||||
|
||||
var target = Expression.Parameter(typeof(object), "target");
|
||||
var castTarget = Expression.Convert(target, method.DeclaringType);
|
||||
var invoke = Expression.Call(castTarget, method, parameters);
|
||||
var instanceParameter = Expression.Parameter(typeof(object), "target");
|
||||
Expression? instance = method.IsStatic
|
||||
? null
|
||||
: Expression.Convert(instanceParameter, method.DeclaringType);
|
||||
|
||||
var invoke = Expression.Call(instance, method, parameters);
|
||||
|
||||
Expression<ExpressionInvoke> lambda;
|
||||
|
||||
if (method.ReturnType != typeof(void))
|
||||
{
|
||||
var result = Expression.Convert(invoke, typeof(object));
|
||||
lambda = Expression.Lambda<ExpressionInvoke>(result, target, argsParameter);
|
||||
lambda = Expression.Lambda<ExpressionInvoke>(result, instanceParameter, argsParameter);
|
||||
}
|
||||
else
|
||||
{
|
||||
var nullResult = Expression.Constant(null, typeof(object));
|
||||
var body = Expression.Block(invoke, nullResult);
|
||||
lambda = Expression.Lambda<ExpressionInvoke>(body, target, argsParameter);
|
||||
lambda = Expression.Lambda<ExpressionInvoke>(body, instanceParameter, argsParameter);
|
||||
}
|
||||
|
||||
return lambda.Compile();
|
||||
|
Loading…
Reference in New Issue
Block a user