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

This makes me want to scream. Calling host.ConnectReceiveEndpoint() inside the bus configuration? Seriously.

@NooNameR
Copy link
Author

NooNameR commented Jul 23, 2019

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 :)

@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