cat on a spaceship
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace Svrnty.CQRS.Abstractions.Attributes;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
||||
public class CommandNameAttribute : Attribute
|
||||
{
|
||||
public CommandNameAttribute(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace Svrnty.CQRS.Abstractions.Attributes;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
||||
public class QueryNameAttribute : Attribute
|
||||
{
|
||||
public QueryNameAttribute(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Svrnty.CQRS.Abstractions.Attributes;
|
||||
|
||||
namespace Svrnty.CQRS.Abstractions.Discovery;
|
||||
|
||||
public sealed class CommandMeta : ICommandMeta
|
||||
{
|
||||
public CommandMeta(Type commandType, Type serviceType, Type commandResultType)
|
||||
{
|
||||
CommandType = commandType;
|
||||
ServiceType = serviceType;
|
||||
CommandResultType = commandResultType;
|
||||
}
|
||||
|
||||
public CommandMeta(Type commandType, Type serviceType)
|
||||
{
|
||||
CommandType = commandType;
|
||||
ServiceType = serviceType;
|
||||
}
|
||||
|
||||
private CommandNameAttribute NameAttribute => CommandType.GetCustomAttribute<CommandNameAttribute>();
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
var name = NameAttribute?.Name ?? CommandType.Name.Replace("Command", string.Empty);
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
public Type CommandType { get; }
|
||||
public Type ServiceType { get; }
|
||||
public Type CommandResultType { get; }
|
||||
|
||||
public string LowerCamelCaseName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(Name))
|
||||
return Name;
|
||||
|
||||
var name = Name;
|
||||
var firstLetter = Char.ToLowerInvariant(name[0]);
|
||||
var ret = $"{firstLetter}{name.Substring(1)}";
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
|
||||
namespace Svrnty.CQRS.Abstractions.Discovery;
|
||||
|
||||
public interface ICommandMeta
|
||||
{
|
||||
string Name { get; }
|
||||
Type CommandType { get; }
|
||||
Type ServiceType { get; }
|
||||
Type CommandResultType { get; }
|
||||
string LowerCamelCaseName { get; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Svrnty.CQRS.Abstractions.Discovery;
|
||||
|
||||
public interface IQueryDiscovery
|
||||
{
|
||||
IQueryMeta FindQuery(string name);
|
||||
IQueryMeta FindQuery(Type queryType);
|
||||
IEnumerable<IQueryMeta> GetQueries();
|
||||
bool QueryExists(string name);
|
||||
bool QueryExists(Type queryType);
|
||||
}
|
||||
|
||||
public interface ICommandDiscovery
|
||||
{
|
||||
bool CommandExists(string name);
|
||||
bool CommandExists(Type commandType);
|
||||
ICommandMeta FindCommand(string name);
|
||||
ICommandMeta FindCommand(Type commandType);
|
||||
IEnumerable<ICommandMeta> GetCommands();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
|
||||
namespace Svrnty.CQRS.Abstractions.Discovery;
|
||||
|
||||
public interface IQueryMeta
|
||||
{
|
||||
string Name { get; }
|
||||
Type QueryType { get; }
|
||||
Type ServiceType { get; }
|
||||
Type QueryResultType { get; }
|
||||
string Category { get; }
|
||||
string LowerCamelCaseName { get; }
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Svrnty.CQRS.Abstractions.Attributes;
|
||||
|
||||
namespace Svrnty.CQRS.Abstractions.Discovery;
|
||||
|
||||
public class QueryMeta : IQueryMeta
|
||||
{
|
||||
public QueryMeta(Type queryType, Type serviceType, Type queryResultType)
|
||||
{
|
||||
QueryType = queryType;
|
||||
ServiceType = serviceType;
|
||||
QueryResultType = queryResultType;
|
||||
}
|
||||
|
||||
protected virtual QueryNameAttribute NameAttribute => QueryType.GetCustomAttribute<QueryNameAttribute>();
|
||||
|
||||
public virtual string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
var name = NameAttribute?.Name ?? QueryType.Name.Replace("Query", string.Empty);
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual Type QueryType { get; }
|
||||
public virtual Type ServiceType { get; }
|
||||
public virtual Type QueryResultType { get; }
|
||||
public virtual string Category => "BasicQuery";
|
||||
|
||||
public string LowerCamelCaseName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(Name))
|
||||
return Name;
|
||||
|
||||
var name = Name;
|
||||
var firstLetter = char.ToLowerInvariant(name[0]);
|
||||
var ret = $"{firstLetter}{name[1..]}";
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Svrnty.CQRS.Abstractions;
|
||||
|
||||
public interface ICommandHandler<in TCommand>
|
||||
where TCommand : class
|
||||
{
|
||||
Task HandleAsync(TCommand command, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
public interface ICommandHandler<in TCommand, TCommandResult>
|
||||
where TCommand : class
|
||||
{
|
||||
Task<TCommandResult> HandleAsync(TCommand command, CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Svrnty.CQRS.Abstractions;
|
||||
|
||||
public interface IQueryHandler<in TQuery, TQueryResult>
|
||||
where TQuery : class
|
||||
{
|
||||
Task<TQueryResult> HandleAsync(TQuery query, CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Svrnty.CQRS.Abstractions.Security;
|
||||
|
||||
public enum AuthorizationResult
|
||||
{
|
||||
Unauthorized,
|
||||
Forbidden,
|
||||
Allowed
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Svrnty.CQRS.Abstractions.Security;
|
||||
|
||||
public interface ICommandAuthorizationService
|
||||
{
|
||||
Task<AuthorizationResult> IsAllowedAsync(Type commandType, CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Svrnty.CQRS.Abstractions.Security;
|
||||
|
||||
public interface IQueryAuthorizationService
|
||||
{
|
||||
Task<AuthorizationResult> IsAllowedAsync(Type queryType, CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Svrnty.CQRS.Abstractions.Discovery;
|
||||
|
||||
namespace Svrnty.CQRS.Abstractions;
|
||||
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
public static IServiceCollection AddQuery<TQuery, TQueryResult, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TQueryHandler>(this IServiceCollection services)
|
||||
where TQuery : class
|
||||
where TQueryHandler : class, IQueryHandler<TQuery, TQueryResult>
|
||||
{
|
||||
// add handler to DI.
|
||||
services.AddTransient<IQueryHandler<TQuery, TQueryResult>, TQueryHandler>();
|
||||
|
||||
// add for discovery purposes.
|
||||
var queryMeta = new QueryMeta(typeof(TQuery), typeof(IQueryHandler<TQuery, TQueryResult>), typeof(TQueryResult));
|
||||
services.AddSingleton<IQueryMeta>(queryMeta);
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddCommand<TCommand, TCommandResult, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TCommandHandler>(this IServiceCollection services)
|
||||
where TCommand : class
|
||||
where TCommandHandler : class, ICommandHandler<TCommand, TCommandResult>
|
||||
{
|
||||
// add handler to DI.
|
||||
services.AddTransient<ICommandHandler<TCommand, TCommandResult>, TCommandHandler>();
|
||||
|
||||
// add for discovery purposes.
|
||||
var commandMeta = new CommandMeta(typeof(TCommand), typeof(ICommandHandler<TCommand>), typeof(TCommandResult));
|
||||
services.AddSingleton<ICommandMeta>(commandMeta);
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddCommand<TCommand, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TCommandHandler>(this IServiceCollection services)
|
||||
where TCommand : class
|
||||
where TCommandHandler : class, ICommandHandler<TCommand>
|
||||
{
|
||||
// add handler to DI.
|
||||
services.AddTransient<ICommandHandler<TCommand>, TCommandHandler>();
|
||||
|
||||
// add for discovery purposes.
|
||||
var commandMeta = new CommandMeta(typeof(TCommand), typeof(ICommandHandler<TCommand>));
|
||||
services.AddSingleton<ICommandMeta>(commandMeta);
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<IsAotCompatible>true</IsAotCompatible>
|
||||
<Authors>David Lebee, Mathias Beaulieu-Duncan</Authors>
|
||||
<LangVersion>14</LangVersion>
|
||||
<Company>Svrnty</Company>
|
||||
<PackageIcon>icon.png</PackageIcon>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<RepositoryUrl>https://github.com/svrnty/dotnet-cqrs</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
|
||||
<DebugType>portable</DebugType>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<IncludeSource>true</IncludeSource>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="..\icon.png" Pack="true" PackagePath="" CopyToOutputDirectory="Always" />
|
||||
<None Include="..\README.md" Pack="true" PackagePath="" CopyToOutputDirectory="Always" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.0-rc.2.25502.107" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user