-
-
Save NooNameR/398494efeaeb2c4c44662eb144d780af to your computer and use it in GitHub Desktop.
| using System; | |
| using System.Collections.Generic; | |
| using System.Linq; | |
| using System.Text; | |
| using System.Threading.Tasks; | |
| using MassTransit; | |
| using Serilog; | |
| using Serilog.Events; | |
| namespace ConsoleApp1 | |
| { | |
| public interface ICommandResult | |
| { | |
| bool Succeeded { get; } | |
| IValidationResult ValidationResult { get; } | |
| Guid CommandId { get; } | |
| object ReferenceId { get; } | |
| } | |
| public class CommandResult : ICommandResult | |
| { | |
| protected CommandResult(Guid commandId, IValidationResult validationResult, object referenceId) | |
| { | |
| ValidationResult = validationResult; | |
| ReferenceId = referenceId; | |
| CommandId = commandId; | |
| } | |
| public bool Succeeded => ValidationResult == null || ValidationResult.IsValid; | |
| public IValidationResult ValidationResult { get; } | |
| public object ReferenceId { get; } | |
| public Guid CommandId { get; } | |
| } | |
| public class FailedCommandResult : CommandResult | |
| { | |
| public FailedCommandResult(Guid commandId, IValidationResult result) : base(commandId, result, null) | |
| { | |
| } | |
| public FailedCommandResult(Guid commandId, string message) : base(commandId, ConsoleApp1.ValidationResult.Error(message), null) | |
| { | |
| } | |
| public FailedCommandResult(Guid commandId, string key, string error) : base(commandId, ConsoleApp1.ValidationResult.Error(key, error), null) | |
| { | |
| } | |
| } | |
| public class SucceededCommandResult : CommandResult | |
| { | |
| public SucceededCommandResult(Guid commandId, object referenceId = null) : base(commandId, ConsoleApp1.ValidationResult.Succeeded, referenceId) | |
| { | |
| } | |
| } | |
| public interface IValidationResult | |
| { | |
| bool IsValid { get; } | |
| string ErrorMessage { get; } | |
| IReadOnlyDictionary<string, IReadOnlyList<string>> Result { get; } | |
| } | |
| public class ValidationResult : IValidationResult | |
| { | |
| public static readonly IValidationResult Succeeded = new ValidationResult(null); | |
| private ValidationResult(string errorMessage, IReadOnlyDictionary<string, IReadOnlyList<string>> result = null) | |
| { | |
| ErrorMessage = errorMessage; | |
| Result = result ?? new Dictionary<string, IReadOnlyList<string>>(); | |
| } | |
| private ValidationResult(string errorMessage, Dictionary<string, List<string>> result) | |
| : this(errorMessage, result?.ToDictionary(x => x.Key, x => (IReadOnlyList<string>)x.Value)) | |
| { | |
| } | |
| public bool IsValid => string.IsNullOrEmpty(ErrorMessage) && Result?.Any() != true; | |
| public string ErrorMessage { get; } | |
| public IReadOnlyDictionary<string, IReadOnlyList<string>> Result { get; } | |
| public static IValidationResult Error(string message) => | |
| new ValidationResult(message); | |
| public static IValidationResult Error(string key, string error) => | |
| new ValidationResult(null, new Dictionary<string, List<string>>(1) {[key] = new List<string>(1) {error}}); | |
| } | |
| public class ValidationResultAggregate : IValidationResult | |
| { | |
| private readonly Dictionary<string, List<string>> _result = new Dictionary<string, List<string>>(); | |
| private readonly StringBuilder _sb = new StringBuilder(); | |
| public bool IsValid => string.IsNullOrEmpty(ErrorMessage) && Result?.Any() != true; | |
| public string ErrorMessage => _sb.ToString(); | |
| public IReadOnlyDictionary<string, IReadOnlyList<string>> Result => _result.ToDictionary(x => x.Key, x => (IReadOnlyList<string>)x.Value); | |
| public ValidationResultAggregate Add(IValidationResult other) | |
| { | |
| if (!string.IsNullOrEmpty(other.ErrorMessage)) | |
| _sb.AppendLine(other.ErrorMessage); | |
| if (other.Result?.Any() != true) | |
| return this; | |
| foreach (var kv in other.Result.Where(x => x.Value.Any())) | |
| { | |
| if (!_result.ContainsKey(kv.Key)) | |
| _result.Add(kv.Key, new List<string>()); | |
| if (_result[kv.Key] == null) | |
| _result[kv.Key] = new List<string>(); | |
| _result[kv.Key].AddRange(kv.Value); | |
| } | |
| return this; | |
| } | |
| } | |
| public class Consumer : IConsumer<ICommandResult> | |
| { | |
| public Task Consume(ConsumeContext<ICommandResult> context) | |
| { | |
| return Task.CompletedTask; | |
| } | |
| } | |
| class Program | |
| { | |
| static async Task Main(string[] args) | |
| { | |
| var logger = new LoggerConfiguration() | |
| .WriteTo.Console(LogEventLevel.Debug) | |
| .CreateLogger(); | |
| var bus = Bus.Factory.CreateUsingRabbitMq(configure => | |
| { | |
| var host = configure.Host(new Uri("rabbitmq://guest:guest@localhost:5672"), h => { }); | |
| configure.UseSerilog(logger); | |
| host.ConnectReceiveEndpoint(cfg => cfg.Consumer(() => new Consumer())); | |
| }); | |
| await bus.StartAsync(); | |
| await bus.Publish<ICommandResult>(new SucceededCommandResult(Guid.NewGuid())); | |
| await Task.Delay(TimeSpan.FromMinutes(1)); | |
| await bus.StopAsync(); | |
| } | |
| } | |
| } |
This makes me want to scream. Calling host.ConnectReceiveEndpoint() inside the bus configuration? Seriously.
Chris, no worries about that, I've been using IEndpointConfiguration always, I can't even remember how to do it without that :)
IReadOnlyDictionary<string, IReadOnlyList<string>> Result this is an issue. if I change it to IDictionary<string, IEnumerable<string>> it works
Yeah, I have a fix, unit tests are passing.
And I feel you, bugs can be frustrating. Thanks for finding it. I always forget about those "extra" interfaces until the collection types.
when you are planning to release a fixed version?
I pushed the fix to develop, not sure what else I have in the develop branch to warrant a release yet. Reviewing open issues at the moment.
no worries, I can fix it in my project, and set a todo in there
This makes me want to scream. Calling host.ConnectReceiveEndpoint() inside the bus configuration? Seriously.