Skip to content

Commit 0647bf0

Browse files
committed
iteration
1 parent 9c156bc commit 0647bf0

19 files changed

+904
-56
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -863,4 +863,6 @@ FodyWeavers.xsd
863863
### VisualStudio Patch ###
864864
# Additional files built by Visual Studio
865865

866-
# End of https://www.toptal.com/developers/gitignore/api/windows,linux,macos,visualstudio,visualstudiocode,intellij,intellij+all,rider,angular,dotnetcore,aspnetcore,xamarinstudio
866+
*.trx
867+
868+
# End of https://www.toptal.com/developers/gitignore/api/windows,linux,macos,visualstudio,visualstudiocode,intellij,intellij+all,rider,angular,dotnetcore,aspnetcore,xamarinstudio

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ If I tell you to remember something, you do the same, update
1010

1111
## Rules to follow
1212
always check all test are passed.
13+
- Prefer static interface members for result/command factories to centralize shared overloads and avoid duplication across result-like types.
1314

1415
# Repository Guidelines
1516

Directory.Build.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
<EnableNETAnalyzers>true</EnableNETAnalyzers>
77
<Nullable>enable</Nullable>
88
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
9+
<EnablePreviewFeatures>true</EnablePreviewFeatures>
910
</PropertyGroup>
1011

1112
<!--NuGet-->

ManagedCode.Communication.Tests/Commands/CommandTests.cs

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,65 @@ public void FromIdValue()
2525
command.Value
2626
.ShouldBe(nameof(Command));
2727
}
28-
}
28+
29+
[Fact]
30+
public void Create_WithEnumType_ShouldSetCommandType()
31+
{
32+
var command = Command.Create(TestCommandType.Delete);
33+
34+
command.CommandType
35+
.ShouldBe(TestCommandType.Delete.ToString());
36+
command.CommandId
37+
.ShouldNotBe(Guid.Empty);
38+
}
39+
40+
[Fact]
41+
public void Create_WithEmptyCommandType_ShouldThrow()
42+
{
43+
Should.Throw<ArgumentException>(() => Command.Create(Guid.NewGuid(), string.Empty));
44+
}
45+
46+
[Fact]
47+
public void GenericCreate_WithValueFactory_ShouldInvokeFactoryOnce()
48+
{
49+
var callCount = 0;
50+
51+
var command = Command<string>.Create(() =>
52+
{
53+
callCount++;
54+
return "payload";
55+
});
56+
57+
callCount
58+
.ShouldBe(1);
59+
command.Value
60+
.ShouldBe("payload");
61+
}
62+
63+
[Fact]
64+
public void GenericCreate_WithEmptyCommandType_ShouldThrow()
65+
{
66+
Should.Throw<ArgumentException>(() => Command<string>.Create(Guid.NewGuid(), string.Empty, "value"));
67+
}
68+
69+
[Fact]
70+
public void GenericFrom_WithCommandType_ShouldReturnCommand()
71+
{
72+
var id = Guid.NewGuid();
73+
var command = Command<string>.From(id, "custom", "value");
74+
75+
command.CommandId
76+
.ShouldBe(id);
77+
command.CommandType
78+
.ShouldBe("custom");
79+
command.Value
80+
.ShouldBe("value");
81+
}
82+
83+
private enum TestCommandType
84+
{
85+
Create,
86+
Update,
87+
Delete
88+
}
89+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using System;
2+
using ManagedCode.Communication.Commands;
3+
using Shouldly;
4+
using Xunit;
5+
6+
namespace ManagedCode.Communication.Tests.Commands;
7+
8+
public class PaginationCommandTests
9+
{
10+
[Fact]
11+
public void Create_WithSkipAndTake_ShouldPopulateProperties()
12+
{
13+
var command = PaginationCommand.Create(10, 5);
14+
15+
command.CommandType
16+
.ShouldBe("Pagination");
17+
command.Skip
18+
.ShouldBe(10);
19+
command.Take
20+
.ShouldBe(5);
21+
command.PageNumber
22+
.ShouldBe(3);
23+
command.PageSize
24+
.ShouldBe(5);
25+
command.Value
26+
.ShouldNotBeNull();
27+
command.Value!.Skip
28+
.ShouldBe(10);
29+
}
30+
31+
[Fact]
32+
public void Create_WithCommandId_ShouldRespectIdentifier()
33+
{
34+
var id = Guid.NewGuid();
35+
36+
var command = PaginationCommand.Create(id, 12, 6);
37+
38+
command.CommandId
39+
.ShouldBe(id);
40+
command.Skip
41+
.ShouldBe(12);
42+
command.Take
43+
.ShouldBe(6);
44+
}
45+
46+
[Fact]
47+
public void Create_WithNegativeSkip_ShouldThrow()
48+
{
49+
Should.Throw<ArgumentOutOfRangeException>(() => PaginationCommand.Create(-1, 10));
50+
}
51+
52+
[Fact]
53+
public void Create_WithNegativeTake_ShouldThrow()
54+
{
55+
Should.Throw<ArgumentOutOfRangeException>(() => PaginationCommand.Create(0, -1));
56+
}
57+
58+
[Fact]
59+
public void FromPage_WithValidParameters_ShouldCalculateSkipAndTake()
60+
{
61+
var command = PaginationCommand.FromPage(3, 20);
62+
63+
command.Skip
64+
.ShouldBe(40);
65+
command.Take
66+
.ShouldBe(20);
67+
command.PageNumber
68+
.ShouldBe(3);
69+
command.PageSize
70+
.ShouldBe(20);
71+
}
72+
73+
[Fact]
74+
public void PaginationRequest_FromPage_InvalidInput_ShouldThrow()
75+
{
76+
Should.Throw<ArgumentOutOfRangeException>(() => PaginationRequest.FromPage(0, 10));
77+
Should.Throw<ArgumentOutOfRangeException>(() => PaginationRequest.FromPage(1, 0));
78+
}
79+
}

ManagedCode.Communication/CollectionResultT/CollectionResultT.Fail.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public static CollectionResult<T> Fail(IEnumerable<T> value)
2222

2323
public static CollectionResult<T> Fail(Problem problem, T[] items)
2424
{
25-
return CollectionResultFactoryBridge<CollectionResult<T>, T>.Fail(problem, items);
25+
return CollectionResult<T>.CreateFailed(problem, items);
2626
}
2727

2828
public static CollectionResult<T> Fail(string title) => ResultFactoryBridge<CollectionResult<T>>.Fail(title);

ManagedCode.Communication/Commands/Command.From.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,16 @@ public partial class Command
66
{
77
public static Command<T> From<T>(Guid id, T value)
88
{
9-
return Command<T>.Create(id, value);
9+
return Command<T>.From(id, value);
1010
}
1111

1212
public static Command<T> From<T>(T value)
1313
{
14-
return Command<T>.Create(value);
14+
return Command<T>.From(value);
1515
}
16-
}
16+
17+
public static Command<T> From<T>(Guid id, string commandType, T value)
18+
{
19+
return Command<T>.From(id, commandType, value);
20+
}
21+
}

ManagedCode.Communication/Commands/Command.cs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace ManagedCode.Communication.Commands;
66

77
[Serializable]
88
[DebuggerDisplay("CommandId: {CommandId}")]
9-
public partial class Command : ICommand
9+
public partial class Command : ICommand, ICommandFactory<Command>
1010
{
1111
[JsonConstructor]
1212
protected Command()
@@ -73,17 +73,34 @@ protected Command(Guid commandId, string commandType)
7373
/// </summary>
7474
public static Command Create(string commandType)
7575
{
76-
return new Command(Guid.CreateVersion7(), commandType);
76+
return CommandFactoryBridge.Create<Command>(commandType);
77+
}
78+
79+
public static Command Create<TEnum>(TEnum commandType)
80+
where TEnum : Enum
81+
{
82+
return CommandFactoryBridge.Create<Command, TEnum>(commandType);
7783
}
7884

7985
/// <summary>
8086
/// Creates a new command with specific ID and type
8187
/// </summary>
8288
public static Command Create(Guid commandId, string commandType)
8389
{
90+
if (string.IsNullOrWhiteSpace(commandType))
91+
{
92+
throw new ArgumentException("Command type must be provided.", nameof(commandType));
93+
}
94+
8495
return new Command(commandId, commandType);
8596
}
8697

98+
public static Command Create<TEnum>(Guid commandId, TEnum commandType)
99+
where TEnum : Enum
100+
{
101+
return CommandFactoryBridge.Create<Command, TEnum>(commandId, commandType);
102+
}
103+
87104
/// <summary>
88105
/// Try to convert CommandType string to an enum value
89106
/// </summary>
@@ -95,4 +112,4 @@ public Result<TEnum> GetCommandTypeAsEnum<TEnum>() where TEnum : struct, Enum
95112
}
96113
return Result<TEnum>.Fail("InvalidCommandType", $"Cannot convert '{CommandType}' to enum {typeof(TEnum).Name}");
97114
}
98-
}
115+
}

ManagedCode.Communication/Commands/CommandT.From.cs

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,47 @@ public partial class Command<T>
66
{
77
public static Command<T> Create(T value)
88
{
9-
return new Command<T>(Guid.CreateVersion7(), value);
9+
return CommandValueFactoryBridge.Create<Command<T>, T>(value);
1010
}
11-
11+
1212
public static Command<T> Create(Guid id, T value)
1313
{
14-
return new Command<T>(id, value);
14+
return CommandValueFactoryBridge.Create<Command<T>, T>(id, value);
1515
}
16-
16+
1717
public static Command<T> Create(Guid id, string commandType, T value)
1818
{
19+
if (string.IsNullOrWhiteSpace(commandType))
20+
{
21+
throw new ArgumentException("Command type must be provided.", nameof(commandType));
22+
}
23+
1924
return new Command<T>(id, commandType, value);
2025
}
21-
26+
27+
public static Command<T> Create(Guid id, string commandType, Func<T> valueFactory)
28+
{
29+
return CommandValueFactoryBridge.Create<Command<T>, T>(id, commandType, valueFactory);
30+
}
31+
32+
public static Command<T> Create(Func<T> valueFactory)
33+
{
34+
return CommandValueFactoryBridge.Create<Command<T>, T>(valueFactory);
35+
}
36+
2237
// Legacy From methods for backward compatibility
2338
public static Command<T> From(Guid id, T value)
2439
{
25-
return Create(id, value);
40+
return CommandValueFactoryBridge.From<Command<T>, T>(id, value);
2641
}
2742

2843
public static Command<T> From(T value)
2944
{
30-
return Create(value);
45+
return CommandValueFactoryBridge.From<Command<T>, T>(value);
46+
}
47+
48+
public static Command<T> From(Guid id, string commandType, T value)
49+
{
50+
return CommandValueFactoryBridge.From<Command<T>, T>(id, commandType, value);
3151
}
32-
}
52+
}

ManagedCode.Communication/Commands/CommandT.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace ManagedCode.Communication.Commands;
77

88
[Serializable]
99
[DebuggerDisplay("CommandId: {CommandId}; {Value?.ToString()}")]
10-
public partial class Command<T> : ICommand<T>
10+
public partial class Command<T> : ICommand<T>, ICommandValueFactory<Command<T>, T>
1111
{
1212
[JsonConstructor]
1313
protected Command()

0 commit comments

Comments
 (0)