mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-07 00:39:00 +08:00
feat(cqrs): 添加CQRS运行时实现和中文文档
- 实现了完整的CQRS分发器,支持命令、查询、通知和流式处理 - 添加了弱键缓存机制确保程序集卸载安全 - 实现了管道行为支持,可添加日志、验证等横切关注点 - 提供了类型安全的请求分发和处理器注册功能 - 编写了详细的CQRS中文文档,涵盖基本用法和最佳实践 - 支持编译期生成处理器注册表优化启动性能
This commit is contained in:
parent
04123d2a71
commit
45ab38519b
@ -387,32 +387,69 @@ internal sealed class CqrsDispatcher(
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存通知分发路径所需的服务类型与强类型调用委托。
|
||||
/// 该绑定把“容器解析哪个服务类型”与“如何调用处理器”聚合到同一缓存项中。
|
||||
/// </summary>
|
||||
private sealed class NotificationDispatchBinding(Type handlerType, NotificationInvoker invoker)
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取通知处理器在容器中的服务类型。
|
||||
/// </summary>
|
||||
public Type HandlerType { get; } = handlerType;
|
||||
|
||||
/// <summary>
|
||||
/// 获取执行通知处理器的强类型调用委托。
|
||||
/// </summary>
|
||||
public NotificationInvoker Invoker { get; } = invoker;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存流式请求分发路径所需的服务类型与调用委托。
|
||||
/// 该绑定让建流热路径只需一次缓存命中即可获得解析与调用所需元数据。
|
||||
/// </summary>
|
||||
private sealed class StreamDispatchBinding(Type handlerType, StreamInvoker invoker)
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取流式请求处理器在容器中的服务类型。
|
||||
/// </summary>
|
||||
public Type HandlerType { get; } = handlerType;
|
||||
|
||||
/// <summary>
|
||||
/// 获取执行流式请求处理器的调用委托。
|
||||
/// </summary>
|
||||
public StreamInvoker Invoker { get; } = invoker;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存普通请求分发路径所需的 handler 服务类型、pipeline 服务类型与强类型调用委托。
|
||||
/// 该绑定同时覆盖“直接请求处理”和“带 pipeline 的请求处理”两条路径。
|
||||
/// </summary>
|
||||
/// <typeparam name="TResponse">请求响应类型。</typeparam>
|
||||
private sealed class RequestDispatchBinding<TResponse>(
|
||||
Type handlerType,
|
||||
Type behaviorType,
|
||||
RequestInvoker<TResponse> requestInvoker,
|
||||
RequestPipelineInvoker<TResponse> pipelineInvoker)
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取请求处理器在容器中的服务类型。
|
||||
/// </summary>
|
||||
public Type HandlerType { get; } = handlerType;
|
||||
|
||||
/// <summary>
|
||||
/// 获取 pipeline 行为在容器中的服务类型。
|
||||
/// </summary>
|
||||
public Type BehaviorType { get; } = behaviorType;
|
||||
|
||||
/// <summary>
|
||||
/// 获取直接调用请求处理器的强类型委托。
|
||||
/// </summary>
|
||||
public RequestInvoker<TResponse> RequestInvoker { get; } = requestInvoker;
|
||||
|
||||
/// <summary>
|
||||
/// 获取执行 pipeline 行为链的强类型委托。
|
||||
/// </summary>
|
||||
public RequestPipelineInvoker<TResponse> PipelineInvoker { get; } = pipelineInvoker;
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,6 +50,39 @@ internal sealed class WeakKeyCache<TKey, TValue>
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定键对应的缓存值;若当前未命中,则在锁保护下使用附加状态创建并写入。
|
||||
/// </summary>
|
||||
/// <typeparam name="TState">创建缓存值时需要携带的附加状态类型。</typeparam>
|
||||
/// <param name="key">缓存键。</param>
|
||||
/// <param name="state">创建缓存值时复用的附加状态。</param>
|
||||
/// <param name="valueFactory">基于键与附加状态创建缓存值的工厂方法。</param>
|
||||
/// <returns>已存在或新创建的缓存值。</returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="key" /> 或 <paramref name="valueFactory" /> 为 <see langword="null" />。
|
||||
/// </exception>
|
||||
public TValue GetOrAdd<TState>(TKey key, TState state, Func<TKey, TState, TValue> valueFactory)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(key);
|
||||
ArgumentNullException.ThrowIfNull(valueFactory);
|
||||
|
||||
var entries = Volatile.Read(ref _entries);
|
||||
if (entries.TryGetValue(key, out var cachedValue))
|
||||
return cachedValue;
|
||||
|
||||
lock (_gate)
|
||||
{
|
||||
entries = _entries;
|
||||
if (entries.TryGetValue(key, out cachedValue))
|
||||
return cachedValue;
|
||||
|
||||
var createdValue = valueFactory(key, state);
|
||||
ArgumentNullException.ThrowIfNull(createdValue);
|
||||
entries.Add(key, createdValue);
|
||||
return createdValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试读取当前缓存中的值,而不触发新的创建逻辑。
|
||||
/// </summary>
|
||||
@ -125,7 +158,8 @@ internal sealed class WeakTypePairCache<TValue>
|
||||
var secondaryEntries = _entries.GetOrAdd(primaryType, static _ => new WeakKeyCache<Type, TValue>());
|
||||
return secondaryEntries.GetOrAdd(
|
||||
secondaryType,
|
||||
_ => valueFactory(primaryType, secondaryType));
|
||||
(PrimaryType: primaryType, Factory: valueFactory),
|
||||
static (cachedSecondaryType, state) => state.Factory(state.PrimaryType, cachedSecondaryType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -83,6 +83,7 @@ public class GetPlayerQuery : QueryBase<GetPlayerInput, PlayerData>
|
||||
处理器负责执行命令或查询的具体逻辑:
|
||||
|
||||
```csharp
|
||||
using GFramework.Cqrs.Command;
|
||||
using GFramework.Cqrs.Cqrs.Command;
|
||||
|
||||
// 命令处理器
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user