Skip to content

Instantly share code, notes, and snippets.

@NooNameR
Created July 23, 2019 14:36
Show Gist options
  • Select an option

  • Save NooNameR/398494efeaeb2c4c44662eb144d780af to your computer and use it in GitHub Desktop.

Select an option

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();
}
}
}
@NooNameR
Copy link
Author

IReadOnlyDictionary<string, IReadOnlyList<string>> Result this is an issue. if I change it to IDictionary<string, IEnumerable<string>> it works

@phatboyg
Copy link

Yeah, I have a fix, unit tests are passing.

@phatboyg
Copy link

And I feel you, bugs can be frustrating. Thanks for finding it. I always forget about those "extra" interfaces until the collection types.

@NooNameR
Copy link
Author

when you are planning to release a fixed version?

@phatboyg
Copy link

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.

@NooNameR
Copy link
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