Created
July 23, 2019 14:36
-
-
Save NooNameR/398494efeaeb2c4c44662eb144d780af to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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(); | |
| } | |
| } | |
| } |
Author
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.
Author
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.
Author
no worries, I can fix it in my project, and set a todo in there
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
IReadOnlyDictionary<string, IReadOnlyList<string>> Resultthis is an issue. if I change it toIDictionary<string, IEnumerable<string>>it works