Skip to content

Commit

Permalink
add DispatcherDataService
Browse files Browse the repository at this point in the history
  • Loading branch information
pwelter34 committed Nov 21, 2024
1 parent bb3f5f2 commit 501e637
Show file tree
Hide file tree
Showing 11 changed files with 403 additions and 8 deletions.
2 changes: 0 additions & 2 deletions src/MediatR.CommandQuery/Commands/EntityIdentifierCommand.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using System.Diagnostics.CodeAnalysis;
using System.Security.Claims;

using Microsoft.Extensions.Logging;

namespace MediatR.CommandQuery.Commands;

public abstract record EntityIdentifierCommand<TKey, TResponse>
Expand Down
2 changes: 0 additions & 2 deletions src/MediatR.CommandQuery/Commands/EntityPatchCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
using MediatR.CommandQuery.Definitions;
using MediatR.CommandQuery.Services;

using Microsoft.Extensions.Logging;

using SystemTextJsonPatch;

namespace MediatR.CommandQuery.Commands;
Expand Down
2 changes: 0 additions & 2 deletions src/MediatR.CommandQuery/Commands/EntityUpdateCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
using MediatR.CommandQuery.Definitions;
using MediatR.CommandQuery.Services;

using Microsoft.Extensions.Logging;

namespace MediatR.CommandQuery.Commands;

public record EntityUpdateCommand<TKey, TUpdateModel, TReadModel>
Expand Down
8 changes: 8 additions & 0 deletions src/MediatR.CommandQuery/Definitions/ISupportSearch.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace MediatR.CommandQuery.Definitions;

public interface ISupportSearch
{
static abstract IEnumerable<string> SearchFields();

static abstract string SortField();
}
178 changes: 178 additions & 0 deletions src/MediatR.CommandQuery/Dispatcher/DispatcherDataService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
using System.Security.Claims;

using MediatR.CommandQuery.Commands;
using MediatR.CommandQuery.Definitions;
using MediatR.CommandQuery.Queries;

namespace MediatR.CommandQuery.Dispatcher;

public class DispatcherDataService : IDispatcherDataService
{
public DispatcherDataService(IDispatcher dispatcher)
{
ArgumentNullException.ThrowIfNull(dispatcher);

Dispatcher = dispatcher;
}


public IDispatcher Dispatcher { get; }


public async Task<TModel?> Get<TKey, TModel>(
TKey id,
TimeSpan? cacheTime = null,
CancellationToken cancellationToken = default)
where TModel : class
{
var user = await GetUser(cancellationToken).ConfigureAwait(false);

var command = new EntityIdentifierQuery<TKey, TModel>(user, id);
command.Cache(cacheTime);

return await Dispatcher.Send(command, cancellationToken).ConfigureAwait(false);
}

public async Task<IReadOnlyCollection<TModel>> Get<TKey, TModel>(
IEnumerable<TKey> ids,
TimeSpan? cacheTime = null,
CancellationToken cancellationToken = default)
where TModel : class
{
var user = await GetUser(cancellationToken).ConfigureAwait(false);

var command = new EntityIdentifiersQuery<TKey, TModel>(user, ids);
command.Cache(cacheTime);

var result = await Dispatcher.Send(command, cancellationToken).ConfigureAwait(false);
return result ?? [];
}

public async Task<IReadOnlyCollection<TModel>> All<TModel>(
string? sortField = null,
TimeSpan? cacheTime = null,
CancellationToken cancellationToken = default)
where TModel : class
{
var filter = new EntityFilter();
var sort = EntitySort.Parse(sortField);

var select = new EntitySelect(filter, sort);

var user = await GetUser(cancellationToken).ConfigureAwait(false);

var command = new EntitySelectQuery<TModel>(user, select);
command.Cache(cacheTime);

var result = await Dispatcher.Send(command, cancellationToken).ConfigureAwait(false);
return result ?? [];
}

public async Task<IReadOnlyCollection<TModel>> Select<TModel>(
EntitySelect? entitySelect = null,
TimeSpan? cacheTime = null,
CancellationToken cancellationToken = default)
where TModel : class
{
var user = await GetUser(cancellationToken).ConfigureAwait(false);

var command = new EntitySelectQuery<TModel>(user, entitySelect);
command.Cache(cacheTime);

var result = await Dispatcher.Send(command, cancellationToken).ConfigureAwait(false);
return result ?? [];
}

public async Task<EntityPagedResult<TModel>> Page<TModel>(
EntityQuery? entityQuery = null,
CancellationToken cancellationToken = default)
where TModel : class
{
var user = await GetUser(cancellationToken).ConfigureAwait(false);

var command = new EntityPagedQuery<TModel>(user, entityQuery);

var result = await Dispatcher.Send(command, cancellationToken).ConfigureAwait(false);

return result ?? new EntityPagedResult<TModel>();
}


public async Task<IEnumerable<TModel>> Search<TModel>(
string searchText,
CancellationToken cancellationToken = default)
where TModel : class, ISupportSearch
{
var filter = EntityFilterBuilder.CreateSearchFilter(TModel.SearchFields(), searchText);
var sort = new EntitySort { Name = TModel.SortField() };

var select = new EntitySelect(filter, sort);

var user = await GetUser(cancellationToken).ConfigureAwait(false);

var command = new EntitySelectQuery<TModel>(user, select);

var result = await Dispatcher.Send(command, cancellationToken).ConfigureAwait(false);
return result ?? [];
}


public async Task<TReadModel?> Save<TKey, TUpdateModel, TReadModel>(
TKey id,
TUpdateModel updateModel,
CancellationToken cancellationToken = default)
where TReadModel : class
where TUpdateModel : class
{
var user = await GetUser(cancellationToken).ConfigureAwait(false);

var command = new EntityUpsertCommand<TKey, TUpdateModel, TReadModel>(user, id, updateModel);

return await Dispatcher.Send(command, cancellationToken).ConfigureAwait(false);
}

public async Task<TReadModel?> Create<TCreateModel, TReadModel>(
TCreateModel createModel,
CancellationToken cancellationToken = default)
where TReadModel : class
where TCreateModel : class
{
var user = await GetUser(cancellationToken).ConfigureAwait(false);

var command = new EntityCreateCommand<TCreateModel, TReadModel>(user, createModel);

return await Dispatcher.Send(command, cancellationToken).ConfigureAwait(false);
}

public async Task<TReadModel?> Update<TKey, TUpdateModel, TReadModel>(
TKey id,
TUpdateModel updateModel,
CancellationToken cancellationToken = default)
where TReadModel : class
where TUpdateModel : class
{
var user = await GetUser(cancellationToken).ConfigureAwait(false);

var command = new EntityUpdateCommand<TKey, TUpdateModel, TReadModel>(user, id, updateModel);

return await Dispatcher.Send(command, cancellationToken).ConfigureAwait(false);
}

public async Task<TReadModel?> Delete<TKey, TReadModel>(
TKey id,
CancellationToken cancellationToken = default)
where TReadModel : class
{
var user = await GetUser(cancellationToken).ConfigureAwait(false);
var command = new EntityDeleteCommand<TKey, TReadModel>(user, id);

return await Dispatcher.Send(command, cancellationToken).ConfigureAwait(false);
}


public virtual Task<ClaimsPrincipal?> GetUser(CancellationToken cancellationToken = default)
{
return Task.FromResult<ClaimsPrincipal?>(null);
}

}
75 changes: 75 additions & 0 deletions src/MediatR.CommandQuery/Dispatcher/IDispatcherDataService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using System.Security.Claims;

using MediatR.CommandQuery.Definitions;
using MediatR.CommandQuery.Queries;

namespace MediatR.CommandQuery.Dispatcher;

public interface IDispatcherDataService
{
IDispatcher Dispatcher { get; }

Task<TModel?> Get<TKey, TModel>(
TKey id,
TimeSpan? cacheTime = null,
CancellationToken cancellationToken = default)
where TModel : class;

Task<IReadOnlyCollection<TModel>> Get<TKey, TModel>(
IEnumerable<TKey> ids,
TimeSpan? cacheTime = null,
CancellationToken cancellationToken = default)
where TModel : class;

Task<IReadOnlyCollection<TModel>> All<TModel>(
string? sortField = null,
TimeSpan? cacheTime = null,
CancellationToken cancellationToken = default)
where TModel : class;

Task<IReadOnlyCollection<TModel>> Select<TModel>(
EntitySelect? entitySelect = null,
TimeSpan? cacheTime = null,
CancellationToken cancellationToken = default)
where TModel : class;

Task<EntityPagedResult<TModel>> Page<TModel>(
EntityQuery? entityQuery = null,
CancellationToken cancellationToken = default)
where TModel : class;


Task<IEnumerable<TModel>> Search<TModel>(
string searchText,
CancellationToken cancellationToken = default)
where TModel : class, ISupportSearch;



Task<TReadModel?> Save<TKey, TUpdateModel, TReadModel>(
TKey id,
TUpdateModel updateModel,
CancellationToken cancellationToken = default)
where TUpdateModel : class
where TReadModel : class;

Task<TReadModel?> Create<TCreateModel, TReadModel>(
TCreateModel createModel,
CancellationToken cancellationToken = default)
where TCreateModel : class
where TReadModel : class;

Task<TReadModel?> Update<TKey, TUpdateModel, TReadModel>(
TKey id,
TUpdateModel updateModel,
CancellationToken cancellationToken = default)
where TUpdateModel : class
where TReadModel : class;

Task<TReadModel?> Delete<TKey, TReadModel>(
TKey id,
CancellationToken cancellationToken = default) where TReadModel : class;


Task<ClaimsPrincipal?> GetUser(CancellationToken cancellationToken = default);
}
4 changes: 4 additions & 0 deletions src/MediatR.CommandQuery/MediatorServiceExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ public static IServiceCollection AddRemoteDispatcher(this IServiceCollection ser
services.TryAddTransient<IDispatcher>(sp => sp.GetRequiredService<RemoteDispatcher>());
services.AddOptions<DispatcherOptions>();

services.TryAddTransient<IDispatcherDataService, DispatcherDataService>();

return services;
}

Expand All @@ -65,6 +67,8 @@ public static IServiceCollection AddServerDispatcher(this IServiceCollection ser
services.TryAddTransient<IDispatcher, MediatorDispatcher>();
services.AddOptions<DispatcherOptions>();

services.TryAddTransient<IDispatcherDataService, DispatcherDataService>();

return services;
}

Expand Down
64 changes: 64 additions & 0 deletions src/MediatR.CommandQuery/Queries/EntityFilterBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@

using MediatR.CommandQuery.Definitions;

namespace MediatR.CommandQuery.Queries;

public static class EntityFilterBuilder
{
public static EntityQuery? CreateSearchQuery<TModel>(string searchText, int page = 1, int pageSize = 20)
where TModel : class, ISupportSearch
{
var filter = CreateSearchFilter<TModel>(searchText);
var sort = CreateSort<TModel>();

return new EntityQuery(filter, sort, page, pageSize);
}

public static EntitySelect? CreateSearchSelect<TModel>(string searchText)
where TModel : class, ISupportSearch
{
var filter = CreateSearchFilter<TModel>(searchText);
var sort = CreateSort<TModel>();

return new EntitySelect(filter, sort);
}

public static EntityFilter? CreateSearchFilter<TModel>(string searchText)
where TModel : class, ISupportSearch
{
return CreateSearchFilter(TModel.SearchFields(), searchText);
}


public static EntitySort? CreateSort<TModel>()
where TModel : class, ISupportSearch
{
return new EntitySort { Name = TModel.SortField() };
}


public static EntityFilter? CreateSearchFilter(IEnumerable<string> fields, string searchText)
{
if (fields is null || string.IsNullOrWhiteSpace(searchText))
return null;

var groupFilter = new EntityFilter
{
Logic = EntityFilterLogic.Or,
Filters = [],
};

foreach (var field in fields)
{
var filter = new EntityFilter
{
Name = field,
Value = searchText,
Operator = EntityFilterOperators.Contains,
};
groupFilter.Filters.Add(filter);
}

return groupFilter;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ protected override void ConfigureApplication(HostApplicationBuilder builder)
services.AddMediator();
services.AddValidatorsFromAssembly<DatabaseFixture>();

services.AddServerDispatcher();

services.AddMediatRCommandQueryEntityFrameworkCoreSqlServerTests();
}
}
Loading

0 comments on commit 501e637

Please sign in to comment.