Skip to content

Commit 3a17cf6

Browse files
committed
-added SendLambdaCommand extension: easily executes specified lambda like it was performed by any regular command handler
-bumped version to 1.25.0
1 parent 28b4a99 commit 3a17cf6

File tree

9 files changed

+640
-1
lines changed

9 files changed

+640
-1
lines changed

Common.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project>
22

33
<PropertyGroup>
4-
<VersionPrefix>1.24.0</VersionPrefix>
4+
<VersionPrefix>1.25.0</VersionPrefix>
55
</PropertyGroup>
66

77
<PropertyGroup>

RELEASE_NOTES.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# RELEASE NOTES
22

3+
## [1.25.0] - 2020-07-27
4+
5+
### Added
6+
- added SendLambdaCommand extension: easily executes specified lambda like it was performed by any regular command handler
7+
38
## [1.24.0] - 2020-06-08
49

510
### Changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System;
2+
3+
namespace Revo.Core.Commands.Lambda
4+
{
5+
public class LambdaCommand : ICommand
6+
{
7+
public LambdaCommand(Delegate @delegate)
8+
{
9+
Delegate = @delegate;
10+
}
11+
12+
public Delegate Delegate { get; }
13+
}
14+
}

Revo.Core/Commands/Lambda/LambdaCommandBusExtensions.cs

Lines changed: 376 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System.Linq;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
using Revo.Core.Core;
5+
6+
namespace Revo.Core.Commands.Lambda
7+
{
8+
public class LambdaCommandHandler :
9+
ICommandHandler<LambdaCommand>
10+
{
11+
private readonly IServiceLocator serviceLocator;
12+
13+
public LambdaCommandHandler(IServiceLocator serviceLocator)
14+
{
15+
this.serviceLocator = serviceLocator;
16+
}
17+
18+
public async Task HandleAsync(LambdaCommand command, CancellationToken cancellationToken)
19+
{
20+
var lambdaParams = command.Delegate.Method.GetParameters()
21+
.Select(x => serviceLocator.Get(x.ParameterType))
22+
.ToArray();
23+
24+
var result = command.Delegate.DynamicInvoke(lambdaParams);
25+
if (result is Task resultTask)
26+
{
27+
await resultTask;
28+
}
29+
}
30+
}
31+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System;
2+
3+
namespace Revo.Core.Commands.Lambda
4+
{
5+
public class LambdaQuery : IQuery<object>
6+
{
7+
public LambdaQuery(Delegate @delegate, Type resultType)
8+
{
9+
Delegate = @delegate;
10+
ResultType = resultType;
11+
}
12+
13+
public Delegate Delegate { get; }
14+
public Type ResultType { get; }
15+
}
16+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System;
2+
using System.Linq;
3+
using System.Threading;
4+
using System.Threading.Tasks;
5+
using Revo.Core.Core;
6+
7+
namespace Revo.Core.Commands.Lambda
8+
{
9+
public class LambdaQueryHandler : IQueryHandler<LambdaQuery, object>
10+
{
11+
private readonly IServiceLocator serviceLocator;
12+
13+
public LambdaQueryHandler(IServiceLocator serviceLocator)
14+
{
15+
this.serviceLocator = serviceLocator;
16+
}
17+
18+
public async Task<object> HandleAsync(LambdaQuery query, CancellationToken cancellationToken)
19+
{
20+
var lambdaParams = query.Delegate.Method.GetParameters()
21+
.Select(x => serviceLocator.Get(x.ParameterType))
22+
.ToArray();
23+
24+
var result = query.Delegate.DynamicInvoke(lambdaParams);
25+
if (result is Task resultTask)
26+
{
27+
await resultTask;
28+
var resultValue = resultTask.GetType().GetProperty(nameof(Task<object>.Result)).GetValue(resultTask);
29+
return resultValue;
30+
}
31+
else
32+
{
33+
return result;
34+
}
35+
}
36+
}
37+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
using System;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
using NSubstitute;
5+
using Revo.Core.Commands.Lambda;
6+
using Revo.Core.Core;
7+
using Xunit;
8+
9+
namespace Revo.Core.Tests.Commands.Lambda
10+
{
11+
public class LambdaCommandHandlerTests
12+
{
13+
private IServiceLocator serviceLocator;
14+
private IDummyService1 dummyService1;
15+
private IDummyService2 dummyService2;
16+
private LambdaCommandHandler sut;
17+
18+
public LambdaCommandHandlerTests()
19+
{
20+
serviceLocator = Substitute.For<IServiceLocator>();
21+
sut = new LambdaCommandHandler(serviceLocator);
22+
23+
dummyService1 = Substitute.For<IDummyService1>();
24+
serviceLocator.Get(typeof(IDummyService1)).Returns(dummyService1);
25+
26+
dummyService2 = Substitute.For<IDummyService2>();
27+
serviceLocator.Get(typeof(IDummyService2)).Returns(dummyService2);
28+
}
29+
30+
[Fact]
31+
public async Task SendLambda_Command()
32+
{
33+
var lambda = Substitute.For<Action>();
34+
await sut.HandleAsync(new LambdaCommand(lambda), CancellationToken.None);
35+
36+
lambda.Received(1).Invoke();
37+
}
38+
39+
[Fact]
40+
public async Task SendLambda_Command_Params1()
41+
{
42+
var lambda = Substitute.For<Action<IDummyService1>>();
43+
await sut.HandleAsync(new LambdaCommand(lambda), CancellationToken.None);
44+
45+
lambda.Received(1).Invoke(dummyService1);
46+
}
47+
48+
[Fact]
49+
public async Task SendLambda_Command_Params2()
50+
{
51+
var lambda = Substitute.For<Action<IDummyService1, IDummyService2>>();
52+
await sut.HandleAsync(new LambdaCommand(lambda), CancellationToken.None);
53+
54+
lambda.Received(1).Invoke(dummyService1, dummyService2);
55+
}
56+
57+
public interface IDummyService1
58+
{
59+
}
60+
61+
public interface IDummyService2
62+
{
63+
}
64+
}
65+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
using System;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
using FluentAssertions;
5+
using NSubstitute;
6+
using Revo.Core.Commands.Lambda;
7+
using Revo.Core.Core;
8+
using Xunit;
9+
10+
namespace Revo.Core.Tests.Commands.Lambda
11+
{
12+
public class LambdaQueryHandlerTests
13+
{
14+
private IServiceLocator serviceLocator;
15+
private IDummyService1 dummyService1;
16+
private IDummyService2 dummyService2;
17+
private LambdaQueryHandler sut;
18+
19+
public LambdaQueryHandlerTests()
20+
{
21+
serviceLocator = Substitute.For<IServiceLocator>();
22+
sut = new LambdaQueryHandler(serviceLocator);
23+
24+
dummyService1 = Substitute.For<IDummyService1>();
25+
serviceLocator.Get(typeof(IDummyService1)).Returns(dummyService1);
26+
27+
dummyService2 = Substitute.For<IDummyService2>();
28+
serviceLocator.Get(typeof(IDummyService2)).Returns(dummyService2);
29+
}
30+
31+
[Fact]
32+
public async Task SendLambda_Query()
33+
{
34+
var lambda = Substitute.For<Func<int>>();
35+
lambda.Invoke().Returns(1);
36+
var result = await sut.HandleAsync(new LambdaQuery(lambda, typeof(int)), CancellationToken.None);
37+
lambda.Received(1).Invoke();
38+
result.Should().Be(1);
39+
}
40+
41+
[Fact]
42+
public async Task SendLambda_Query_Params1()
43+
{
44+
var lambda = Substitute.For<Func<IDummyService1, int>>();
45+
lambda.Invoke(dummyService1).Returns(1);
46+
var result = await sut.HandleAsync(new LambdaQuery(lambda, typeof(int)), CancellationToken.None);
47+
result.Should().Be(1);
48+
}
49+
50+
[Fact]
51+
public async Task SendLambda_Query_Params2()
52+
{
53+
var lambda = Substitute.For<Func<IDummyService1, IDummyService2, int>>();
54+
lambda.Invoke(dummyService1, dummyService2).Returns(1);
55+
var result = await sut.HandleAsync(new LambdaQuery(lambda, typeof(int)), CancellationToken.None);
56+
result.Should().Be(1);
57+
}
58+
59+
[Fact]
60+
public async Task SendLambda_Query_Task()
61+
{
62+
var lambda = Substitute.For<Func<Task<int>>>();
63+
lambda.Invoke().Returns(1);
64+
var result = await sut.HandleAsync(new LambdaQuery(lambda, typeof(int)), CancellationToken.None);
65+
lambda.Received(1).Invoke();
66+
result.Should().Be(1);
67+
}
68+
69+
[Fact]
70+
public async Task SendLambda_Query_Task_Params1()
71+
{
72+
var lambda = Substitute.For<Func<IDummyService1, Task<int>>>();
73+
lambda.Invoke(dummyService1).Returns(1);
74+
var result = await sut.HandleAsync(new LambdaQuery(lambda, typeof(int)), CancellationToken.None);
75+
result.Should().Be(1);
76+
}
77+
78+
[Fact]
79+
public async Task SendLambda_Query_Task_Params2()
80+
{
81+
var lambda = Substitute.For<Func<IDummyService1, IDummyService2, Task<int>>>();
82+
lambda.Invoke(dummyService1, dummyService2).Returns(1);
83+
var result = await sut.HandleAsync(new LambdaQuery(lambda, typeof(int)), CancellationToken.None);
84+
result.Should().Be(1);
85+
}
86+
87+
public interface IDummyService1
88+
{
89+
}
90+
91+
public interface IDummyService2
92+
{
93+
}
94+
}
95+
}

0 commit comments

Comments
 (0)