Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions Revo.Core/Collections/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ public static string ToSeparatedString(this IEnumerable source, char separator)
return sb.ToString();
}

public static IEnumerable<T> AsNotNull<T>(this IEnumerable<T> original)
{
return original ?? Enumerable.Empty<T>();
}
public static IEnumerable<T> AsNotNull<T>(this IEnumerable<T> original) =>
original ?? Enumerable.Empty<T>();
}
}
89 changes: 21 additions & 68 deletions Revo.Core/Collections/MultiValueDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,47 +7,28 @@ namespace Revo.Core.Collections
public class MultiValueDictionary<TKey, TValue> : IReadOnlyDictionary<TKey, IReadOnlyCollection<TValue>>
{
private readonly Dictionary<TKey, List<TValue>> dictionary;
public MultiValueDictionary()
{
public MultiValueDictionary() =>
dictionary = new Dictionary<TKey, List<TValue>>();
}

public MultiValueDictionary(IEqualityComparer<TKey> comparer)
{
public MultiValueDictionary(IEqualityComparer<TKey> comparer) =>
dictionary = new Dictionary<TKey, List<TValue>>(comparer);
}

public MultiValueDictionary(int capacity)
{
public MultiValueDictionary(int capacity) =>
dictionary = new Dictionary<TKey, List<TValue>>(capacity);
}

public MultiValueDictionary(int capacity, IEqualityComparer<TKey> comparer)
{
public MultiValueDictionary(int capacity, IEqualityComparer<TKey> comparer) =>
dictionary = new Dictionary<TKey, List<TValue>>(capacity, comparer);
}

public MultiValueDictionary(IEnumerable<KeyValuePair<TKey, IReadOnlyCollection<TValue>>> enumerable) : this()
{
public MultiValueDictionary(IEnumerable<KeyValuePair<TKey, IReadOnlyCollection<TValue>>> enumerable) : this() =>
AddRange(enumerable);
}

public MultiValueDictionary(IEnumerable<KeyValuePair<TKey, IReadOnlyCollection<TValue>>> enumerable,
IEqualityComparer<TKey> comparer) : this(comparer)
{
AddRange(enumerable);
}
IEqualityComparer<TKey> comparer) : this(comparer) => AddRange(enumerable);

public MultiValueDictionary(IEnumerable<IGrouping<TKey, TValue>> values) : this()
{
AddRange(values);
}
public MultiValueDictionary(IEnumerable<IGrouping<TKey, TValue>> values) : this() => AddRange(values);

public MultiValueDictionary(IEnumerable<IGrouping<TKey, TValue>> values,
IEqualityComparer<TKey> comparer) : this(comparer)
{
AddRange(values);
}
IEqualityComparer<TKey> comparer) : this(comparer) => AddRange(values);

public IReadOnlyCollection<TValue> this[TKey key]
{
Expand Down Expand Up @@ -112,32 +93,21 @@ public void AddRange(IEnumerable<IGrouping<TKey, TValue>> values)
}
}

public void Clear()
{
dictionary.Clear();
}
public void Clear() => dictionary.Clear();

public bool ContainsKey(TKey key)
{
return dictionary.ContainsKey(key);
}
public bool ContainsKey(TKey key) => dictionary.ContainsKey(key);

public IEnumerator<KeyValuePair<TKey, IReadOnlyCollection<TValue>>> GetEnumerator() =>
new Enumerator(dictionary.GetEnumerator());

public IEnumerator<KeyValuePair<TKey, IReadOnlyCollection<TValue>>> GetEnumerator()
{
return new Enumerator(dictionary.GetEnumerator());
}

public bool TryGetValue(TKey key, out IReadOnlyCollection<TValue> value)
{
bool result = dictionary.TryGetValue(key, out var listValue);
value = listValue;
return result;
}

public bool Remove(TKey key)
{
return dictionary.Remove(key);
}
public bool Remove(TKey key) => dictionary.Remove(key);

public bool Remove(TKey key, TValue value)
{
Expand All @@ -153,30 +123,16 @@ public bool Remove(TKey key, TValue value)

return false;
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

private class Enumerator : IEnumerator<KeyValuePair<TKey, IReadOnlyCollection<TValue>>>
{
private readonly IEnumerator<KeyValuePair<TKey, List<TValue>>> enumerator;
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

public Enumerator(IEnumerator<KeyValuePair<TKey, List<TValue>>> enumerator)
{
this.enumerator = enumerator;
}
private class Enumerator(IEnumerator<KeyValuePair<TKey, List<TValue>>> enumerator) : IEnumerator<KeyValuePair<TKey, IReadOnlyCollection<TValue>>>
{
private readonly IEnumerator<KeyValuePair<TKey, List<TValue>>> enumerator = enumerator;

public bool MoveNext()
{
return enumerator.MoveNext();
}
public bool MoveNext() => enumerator.MoveNext();

public void Reset()
{
enumerator.Reset();
}
public void Reset() => enumerator.Reset();

public KeyValuePair<TKey, IReadOnlyCollection<TValue>> Current =>
new KeyValuePair<TKey, IReadOnlyCollection<TValue>>(
Expand All @@ -185,10 +141,7 @@ public void Reset()

object IEnumerator.Current => ((IEnumerator)enumerator).Current;

public void Dispose()
{
enumerator.Dispose();
}
public void Dispose() => enumerator.Dispose();
}
}
}
17 changes: 5 additions & 12 deletions Revo.Core/Commands/CommandBusMiddlewareFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,13 @@

namespace Revo.Core.Commands
{
public class CommandBusMiddlewareFactory : ICommandBusMiddlewareFactory
public class CommandBusMiddlewareFactory(IServiceLocator serviceLocator) : ICommandBusMiddlewareFactory
{
private readonly IServiceLocator serviceLocator;

public CommandBusMiddlewareFactory(IServiceLocator serviceLocator)
{
this.serviceLocator = serviceLocator;
}
private readonly IServiceLocator serviceLocator = serviceLocator;

public ICommandBusMiddleware<TCommand>[] CreateMiddlewares<TCommand>(ICommandBus commandBus)
where TCommand : class, ICommandBase
{
return serviceLocator.GetAll<ICommandBusMiddleware<TCommand>>()
.ToArray();
}
where TCommand : class, ICommandBase =>
serviceLocator.GetAll<ICommandBusMiddleware<TCommand>>()
.ToArray();
}
}
9 changes: 2 additions & 7 deletions Revo.Core/Commands/CommandBusPipeline.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,10 @@ namespace Revo.Core.Commands
/// and filters.
/// </summary>
/// <typeparam name="T"></typeparam>
public class CommandBusPipeline : ICommandBusPipeline
public class CommandBusPipeline(ICommandBusMiddlewareFactory middlewareFactory) : ICommandBusPipeline
{
private readonly ICommandBusMiddlewareFactory middlewareFactory;
private readonly ICommandBusMiddlewareFactory middlewareFactory = middlewareFactory;

public CommandBusPipeline(ICommandBusMiddlewareFactory middlewareFactory)
{
this.middlewareFactory = middlewareFactory;
}

public Task<object> ProcessAsync(ICommandBase command, CommandBusMiddlewareDelegate executionHandler,
ICommandBus commandBus, CommandExecutionOptions executionOptions, CancellationToken cancellationToken)
{
Expand Down
12 changes: 3 additions & 9 deletions Revo.Core/Commands/CommandContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,9 @@

namespace Revo.Core.Commands
{
public class CommandContext : ICommandContext
public class CommandContext(ICommandBase currentCommand, IUnitOfWork unitOfWork) : ICommandContext
{
public CommandContext(ICommandBase currentCommand, IUnitOfWork unitOfWork)
{
CurrentCommand = currentCommand;
UnitOfWork = unitOfWork;
}

public ICommandBase CurrentCommand { get; }
public IUnitOfWork UnitOfWork { get; }
public ICommandBase CurrentCommand { get; } = currentCommand;
public IUnitOfWork UnitOfWork { get; } = unitOfWork;
}
}
10 changes: 2 additions & 8 deletions Revo.Core/Commands/CommandContextStack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,8 @@ public class CommandContextStack : ICommandContext, IUnitOfWorkAccessor
public IUnitOfWork UnitOfWork => contexts.Count > 0 ? contexts.Peek().UnitOfWork : null;
public ICommandContext PeekOrDefault => contexts.Count > 0 ? contexts.Peek() : null;

public void Push(ICommandContext context)
{
contexts.Push(context);
}
public void Push(ICommandContext context) => contexts.Push(context);

public ICommandContext Pop()
{
return contexts.Pop();
}
public ICommandContext Pop() => contexts.Pop();
}
}
20 changes: 6 additions & 14 deletions Revo.Core/Commands/CommandExecutionOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,20 @@
/// <remarks>Note that some of the options may actually be used only if command is handled
/// using a command handler with local command handler pipeline (e.g. they may have no
/// significance if a remote command handler is registered for the command).</remarks>
public class CommandExecutionOptions
public class CommandExecutionOptions(bool? autoCommitUnitOfWork = null,
CommandTenantContextOverride tenantContext = null)
{
public static readonly CommandExecutionOptions Default = new CommandExecutionOptions(null, null);

public CommandExecutionOptions(bool? autoCommitUnitOfWork = null,
CommandTenantContextOverride tenantContext = null)
{
AutoCommitUnitOfWork = autoCommitUnitOfWork;
TenantContext = tenantContext;
}

/// <summary>
/// Should the command handle middleware automatically start new unit of work and commit it upon
/// its successful completion? Default to null, which implicitly enables this behavior for ICommand
/// commands (not IQuery queries).
/// </summary>
public bool? AutoCommitUnitOfWork { get; }
public CommandTenantContextOverride TenantContext { get; }
public bool? AutoCommitUnitOfWork { get; } = autoCommitUnitOfWork;
public CommandTenantContextOverride TenantContext { get; } = tenantContext;

public CommandExecutionOptions WithTenantContext(CommandTenantContextOverride tenantContextOverride)
{
return new CommandExecutionOptions(AutoCommitUnitOfWork, tenantContextOverride);
}
public CommandExecutionOptions WithTenantContext(CommandTenantContextOverride tenantContextOverride) =>
new CommandExecutionOptions(AutoCommitUnitOfWork, tenantContextOverride);
}
}
21 changes: 6 additions & 15 deletions Revo.Core/Commands/CommandGateway.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,9 @@

namespace Revo.Core.Commands
{
public class CommandGateway : ICommandGateway
public class CommandGateway(ICommandRouter commandRouter) : ICommandGateway
{
private readonly ICommandRouter commandRouter;

public CommandGateway(ICommandRouter commandRouter)
{
this.commandRouter = commandRouter;
}
private readonly ICommandRouter commandRouter = commandRouter;

public Task SendAsync(ICommandBase command, CommandExecutionOptions executionOptions,
CancellationToken cancellationToken = default(CancellationToken))
Expand All @@ -21,10 +16,8 @@ public Task SendAsync(ICommandBase command, CommandExecutionOptions executionOpt
return commandBus.SendAsync(command, executionOptions, cancellationToken);
}

public Task<TResult> SendAsync<TResult>(ICommand<TResult> command, CancellationToken cancellationToken = default(CancellationToken))
{
return SendAsync(command, CommandExecutionOptions.Default, cancellationToken);
}
public Task<TResult> SendAsync<TResult>(ICommand<TResult> command, CancellationToken cancellationToken = default(CancellationToken)) =>
SendAsync(command, CommandExecutionOptions.Default, cancellationToken);

public Task<TResult> SendAsync<TResult>(ICommand<TResult> command, CommandExecutionOptions executionOptions,
CancellationToken cancellationToken = default(CancellationToken))
Expand All @@ -34,9 +27,7 @@ public Task<TResult> SendAsync<TResult>(ICommand<TResult> command, CommandExecut
return commandBus.SendAsync(command, executionOptions, cancellationToken);
}

public Task SendAsync(ICommandBase command, CancellationToken cancellationToken = default(CancellationToken))
{
return SendAsync(command, CommandExecutionOptions.Default, cancellationToken);
}
public Task SendAsync(ICommandBase command, CancellationToken cancellationToken = default(CancellationToken)) =>
SendAsync(command, CommandExecutionOptions.Default, cancellationToken);
}
}
8 changes: 3 additions & 5 deletions Revo.Core/Commands/CommandHandlerBindingExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,11 @@ public static IBindingNamedWithOrOnSyntax<object> BindCommandHandler(
.InTaskScope();
}

public static Type[] GetCommandHandlerInterfaces(Type commandHandlerType)
{
return commandHandlerType.GetInterfaces()
public static Type[] GetCommandHandlerInterfaces(Type commandHandlerType) =>
commandHandlerType.GetInterfaces()
.Where(x => x.IsGenericType
&& new[] {typeof(ICommandHandler<>), typeof(ICommandHandler<,>)}
&& new[] { typeof(ICommandHandler<>), typeof(ICommandHandler<,>) }
.Contains(x.GetGenericTypeDefinition()))
.ToArray();
}
}
}
25 changes: 7 additions & 18 deletions Revo.Core/Commands/CommandHandlerDiscovery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,15 @@

namespace Revo.Core.Commands
{
public class CommandHandlerDiscovery : IApplicationConfigurer
public class CommandHandlerDiscovery(ITypeExplorer typeExplorer, StandardKernel kernel,
ICommandRouter commandRouter, ILogger logger) : IApplicationConfigurer
{
private readonly ITypeExplorer typeExplorer;
private readonly StandardKernel kernel;
private readonly ICommandRouter commandRouter;
private readonly ILogger logger;
private readonly ITypeExplorer typeExplorer = typeExplorer;
private readonly StandardKernel kernel = kernel;
private readonly ICommandRouter commandRouter = commandRouter;
private readonly ILogger logger = logger;

public CommandHandlerDiscovery(ITypeExplorer typeExplorer, StandardKernel kernel,
ICommandRouter commandRouter, ILogger logger)
{
this.typeExplorer = typeExplorer;
this.kernel = kernel;
this.commandRouter = commandRouter;
this.logger = logger;
}

public void Configure()
{
DiscoverCommandHandlers();
}
public void Configure() => DiscoverCommandHandlers();

private void DiscoverCommandHandlers()
{
Expand Down
9 changes: 2 additions & 7 deletions Revo.Core/Commands/CommandRouter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,12 @@

namespace Revo.Core.Commands
{
public class CommandRouter : ICommandRouter
public class CommandRouter(ILogger logger) : ICommandRouter
{
private readonly ILogger logger;
private readonly ILogger logger = logger;

private readonly Dictionary<Type, Func<ICommandBus>> routes = new Dictionary<Type, Func<ICommandBus>>();

public CommandRouter(ILogger logger)
{
this.logger = logger;
}

public void AddRoute(Type commandType, Func<ICommandBus> commandBus)
{
if (!typeof(ICommandBase).IsAssignableFrom(commandType))
Expand Down
Loading