mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-07 00:39:00 +08:00
refactor(cqrs): 扩展指针类型注册生成覆盖
- 优化 CqrsHandlerRegistryGenerator 对 pointer 类型的 runtime type 递归重建与发射逻辑 - 修复 function pointer 签名默认直出导致隐藏类型漏回退的判定边界 - 补充 pointer precise registration 与 function pointer fallback 回归测试 - 更新 cqrs-rewrite 跟踪与 trace 到 RP-047
This commit is contained in:
parent
7cf0a75568
commit
5f3964d4c0
@ -412,6 +412,13 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type is IPointerTypeSymbol pointerType &&
|
||||||
|
TryCreateRuntimeTypeReference(compilation, pointerType.PointedAtType, out var pointedAtTypeReference))
|
||||||
|
{
|
||||||
|
runtimeTypeReference = RuntimeTypeReferenceSpec.FromPointer(pointedAtTypeReference!);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (type is INamedTypeSymbol genericNamedType &&
|
if (type is INamedTypeSymbol genericNamedType &&
|
||||||
genericNamedType.IsGenericType &&
|
genericNamedType.IsGenericType &&
|
||||||
!genericNamedType.IsUnboundGenericType &&
|
!genericNamedType.IsUnboundGenericType &&
|
||||||
@ -520,6 +527,17 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator
|
|||||||
return true;
|
return true;
|
||||||
case IPointerTypeSymbol pointerType:
|
case IPointerTypeSymbol pointerType:
|
||||||
return CanReferenceFromGeneratedRegistry(compilation, pointerType.PointedAtType);
|
return CanReferenceFromGeneratedRegistry(compilation, pointerType.PointedAtType);
|
||||||
|
case IFunctionPointerTypeSymbol functionPointerType:
|
||||||
|
if (!CanReferenceFromGeneratedRegistry(compilation, functionPointerType.Signature.ReturnType))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach (var parameter in functionPointerType.Signature.Parameters)
|
||||||
|
{
|
||||||
|
if (!CanReferenceFromGeneratedRegistry(compilation, parameter.Type))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
case ITypeParameterSymbol:
|
case ITypeParameterSymbol:
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
@ -975,6 +993,18 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator
|
|||||||
: $"{elementExpression}.MakeArrayType({runtimeTypeReference.ArrayRank})";
|
: $"{elementExpression}.MakeArrayType({runtimeTypeReference.ArrayRank})";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (runtimeTypeReference.PointerElementTypeReference is not null)
|
||||||
|
{
|
||||||
|
var pointedAtExpression = AppendRuntimeTypeReferenceResolution(
|
||||||
|
builder,
|
||||||
|
runtimeTypeReference.PointerElementTypeReference,
|
||||||
|
$"{variableBaseName}PointedAt",
|
||||||
|
reflectedArgumentNames,
|
||||||
|
indent);
|
||||||
|
|
||||||
|
return $"{pointedAtExpression}.MakePointerType()";
|
||||||
|
}
|
||||||
|
|
||||||
if (runtimeTypeReference.GenericTypeDefinitionReference is not null)
|
if (runtimeTypeReference.GenericTypeDefinitionReference is not null)
|
||||||
{
|
{
|
||||||
var genericTypeDefinitionExpression = AppendRuntimeTypeReferenceResolution(
|
var genericTypeDefinitionExpression = AppendRuntimeTypeReferenceResolution(
|
||||||
@ -1091,6 +1121,12 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (runtimeTypeReference.PointerElementTypeReference is not null &&
|
||||||
|
ContainsExternalAssemblyTypeLookup(runtimeTypeReference.PointerElementTypeReference))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (runtimeTypeReference.GenericTypeDefinitionReference is not null &&
|
if (runtimeTypeReference.GenericTypeDefinitionReference is not null &&
|
||||||
ContainsExternalAssemblyTypeLookup(runtimeTypeReference.GenericTypeDefinitionReference))
|
ContainsExternalAssemblyTypeLookup(runtimeTypeReference.GenericTypeDefinitionReference))
|
||||||
{
|
{
|
||||||
@ -1129,18 +1165,19 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator
|
|||||||
string? ReflectionAssemblyName,
|
string? ReflectionAssemblyName,
|
||||||
RuntimeTypeReferenceSpec? ArrayElementTypeReference,
|
RuntimeTypeReferenceSpec? ArrayElementTypeReference,
|
||||||
int ArrayRank,
|
int ArrayRank,
|
||||||
|
RuntimeTypeReferenceSpec? PointerElementTypeReference,
|
||||||
RuntimeTypeReferenceSpec? GenericTypeDefinitionReference,
|
RuntimeTypeReferenceSpec? GenericTypeDefinitionReference,
|
||||||
ImmutableArray<RuntimeTypeReferenceSpec> GenericTypeArguments)
|
ImmutableArray<RuntimeTypeReferenceSpec> GenericTypeArguments)
|
||||||
{
|
{
|
||||||
public static RuntimeTypeReferenceSpec FromDirectReference(string typeDisplayName)
|
public static RuntimeTypeReferenceSpec FromDirectReference(string typeDisplayName)
|
||||||
{
|
{
|
||||||
return new RuntimeTypeReferenceSpec(typeDisplayName, null, null, null, 0, null,
|
return new RuntimeTypeReferenceSpec(typeDisplayName, null, null, null, 0, null, null,
|
||||||
ImmutableArray<RuntimeTypeReferenceSpec>.Empty);
|
ImmutableArray<RuntimeTypeReferenceSpec>.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RuntimeTypeReferenceSpec FromReflectionLookup(string reflectionTypeMetadataName)
|
public static RuntimeTypeReferenceSpec FromReflectionLookup(string reflectionTypeMetadataName)
|
||||||
{
|
{
|
||||||
return new RuntimeTypeReferenceSpec(null, reflectionTypeMetadataName, null, null, 0, null,
|
return new RuntimeTypeReferenceSpec(null, reflectionTypeMetadataName, null, null, 0, null, null,
|
||||||
ImmutableArray<RuntimeTypeReferenceSpec>.Empty);
|
ImmutableArray<RuntimeTypeReferenceSpec>.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1149,13 +1186,19 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator
|
|||||||
string reflectionTypeMetadataName)
|
string reflectionTypeMetadataName)
|
||||||
{
|
{
|
||||||
return new RuntimeTypeReferenceSpec(null, reflectionTypeMetadataName, reflectionAssemblyName, null, 0,
|
return new RuntimeTypeReferenceSpec(null, reflectionTypeMetadataName, reflectionAssemblyName, null, 0,
|
||||||
null,
|
null, null,
|
||||||
ImmutableArray<RuntimeTypeReferenceSpec>.Empty);
|
ImmutableArray<RuntimeTypeReferenceSpec>.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RuntimeTypeReferenceSpec FromArray(RuntimeTypeReferenceSpec elementTypeReference, int arrayRank)
|
public static RuntimeTypeReferenceSpec FromArray(RuntimeTypeReferenceSpec elementTypeReference, int arrayRank)
|
||||||
{
|
{
|
||||||
return new RuntimeTypeReferenceSpec(null, null, null, elementTypeReference, arrayRank, null,
|
return new RuntimeTypeReferenceSpec(null, null, null, elementTypeReference, arrayRank, null, null,
|
||||||
|
ImmutableArray<RuntimeTypeReferenceSpec>.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RuntimeTypeReferenceSpec FromPointer(RuntimeTypeReferenceSpec pointedAtTypeReference)
|
||||||
|
{
|
||||||
|
return new RuntimeTypeReferenceSpec(null, null, null, null, 0, pointedAtTypeReference, null,
|
||||||
ImmutableArray<RuntimeTypeReferenceSpec>.Empty);
|
ImmutableArray<RuntimeTypeReferenceSpec>.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1163,7 +1206,7 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator
|
|||||||
RuntimeTypeReferenceSpec genericTypeDefinitionReference,
|
RuntimeTypeReferenceSpec genericTypeDefinitionReference,
|
||||||
ImmutableArray<RuntimeTypeReferenceSpec> genericTypeArguments)
|
ImmutableArray<RuntimeTypeReferenceSpec> genericTypeArguments)
|
||||||
{
|
{
|
||||||
return new RuntimeTypeReferenceSpec(null, null, null, null, 0, genericTypeDefinitionReference,
|
return new RuntimeTypeReferenceSpec(null, null, null, null, 0, null, genericTypeDefinitionReference,
|
||||||
genericTypeArguments);
|
genericTypeArguments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -164,6 +164,45 @@ public class CqrsHandlerRegistryGeneratorTests
|
|||||||
|
|
||||||
""";
|
""";
|
||||||
|
|
||||||
|
private const string HiddenPointerResponseExpected = """
|
||||||
|
// <auto-generated />
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
[assembly: global::GFramework.Cqrs.CqrsHandlerRegistryAttribute(typeof(global::GFramework.Generated.Cqrs.__GFrameworkGeneratedCqrsHandlerRegistry))]
|
||||||
|
|
||||||
|
namespace GFramework.Generated.Cqrs;
|
||||||
|
|
||||||
|
internal sealed class __GFrameworkGeneratedCqrsHandlerRegistry : global::GFramework.Cqrs.ICqrsHandlerRegistry
|
||||||
|
{
|
||||||
|
public void Register(global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, global::GFramework.Core.Abstractions.Logging.ILogger logger)
|
||||||
|
{
|
||||||
|
if (services is null)
|
||||||
|
throw new global::System.ArgumentNullException(nameof(services));
|
||||||
|
if (logger is null)
|
||||||
|
throw new global::System.ArgumentNullException(nameof(logger));
|
||||||
|
|
||||||
|
var registryAssembly = typeof(global::GFramework.Generated.Cqrs.__GFrameworkGeneratedCqrsHandlerRegistry).Assembly;
|
||||||
|
|
||||||
|
var implementationType0 = typeof(global::TestApp.Container.HiddenHandler);
|
||||||
|
if (implementationType0 is not null)
|
||||||
|
{
|
||||||
|
var serviceType0_0Argument0 = registryAssembly.GetType("TestApp.Container+HiddenRequest", throwOnError: false, ignoreCase: false);
|
||||||
|
var serviceType0_0Argument1PointedAt = registryAssembly.GetType("TestApp.Container+HiddenResponse", throwOnError: false, ignoreCase: false);
|
||||||
|
if (serviceType0_0Argument0 is not null && serviceType0_0Argument1PointedAt is not null)
|
||||||
|
{
|
||||||
|
var serviceType0_0 = typeof(global::GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler<,>).MakeGenericType(serviceType0_0Argument0, serviceType0_0Argument1PointedAt.MakePointerType());
|
||||||
|
global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient(
|
||||||
|
services,
|
||||||
|
serviceType0_0,
|
||||||
|
implementationType0);
|
||||||
|
logger.Debug("Registered CQRS handler TestApp.Container.HiddenHandler as GFramework.Cqrs.Abstractions.Cqrs.IRequestHandler<TestApp.Container.HiddenRequest, TestApp.Container.HiddenResponse*>.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
""";
|
||||||
|
|
||||||
private const string MixedDirectAndPreciseRegistrationsExpected = """
|
private const string MixedDirectAndPreciseRegistrationsExpected = """
|
||||||
// <auto-generated />
|
// <auto-generated />
|
||||||
#nullable enable
|
#nullable enable
|
||||||
@ -745,6 +784,98 @@ public class CqrsHandlerRegistryGeneratorTests
|
|||||||
("CqrsHandlerRegistry.g.cs", HiddenGenericEnvelopeResponseExpected));
|
("CqrsHandlerRegistry.g.cs", HiddenGenericEnvelopeResponseExpected));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 验证精确重建路径会递归覆盖隐藏指针元素类型,
|
||||||
|
/// 使“隐藏 pointed-at 类型 + unsafe 指针响应”的 handler 也能直接生成 closed service type。
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public async Task Generates_Precise_Service_Type_For_Hidden_Pointer_Response()
|
||||||
|
{
|
||||||
|
const string source = """
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.DependencyInjection
|
||||||
|
{
|
||||||
|
public interface IServiceCollection { }
|
||||||
|
|
||||||
|
public static class ServiceCollectionServiceExtensions
|
||||||
|
{
|
||||||
|
public static void AddTransient(IServiceCollection services, Type serviceType, Type implementationType) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace GFramework.Core.Abstractions.Logging
|
||||||
|
{
|
||||||
|
public interface ILogger
|
||||||
|
{
|
||||||
|
void Debug(string msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace GFramework.Cqrs.Abstractions.Cqrs
|
||||||
|
{
|
||||||
|
public interface IRequest<TResponse> { }
|
||||||
|
public interface INotification { }
|
||||||
|
public interface IStreamRequest<TResponse> { }
|
||||||
|
|
||||||
|
public interface IRequestHandler<in TRequest, TResponse> where TRequest : IRequest<TResponse> { }
|
||||||
|
public interface INotificationHandler<in TNotification> where TNotification : INotification { }
|
||||||
|
public interface IStreamRequestHandler<in TRequest, out TResponse> where TRequest : IStreamRequest<TResponse> { }
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace GFramework.Cqrs
|
||||||
|
{
|
||||||
|
public interface ICqrsHandlerRegistry
|
||||||
|
{
|
||||||
|
void Register(Microsoft.Extensions.DependencyInjection.IServiceCollection services, GFramework.Core.Abstractions.Logging.ILogger logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
|
||||||
|
public sealed class CqrsHandlerRegistryAttribute : Attribute
|
||||||
|
{
|
||||||
|
public CqrsHandlerRegistryAttribute(Type registryType) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace TestApp
|
||||||
|
{
|
||||||
|
using GFramework.Cqrs.Abstractions.Cqrs;
|
||||||
|
|
||||||
|
public sealed class Container
|
||||||
|
{
|
||||||
|
private unsafe struct HiddenResponse
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private unsafe sealed record HiddenRequest() : IRequest<HiddenResponse*>;
|
||||||
|
|
||||||
|
public unsafe sealed class HiddenHandler : IRequestHandler<HiddenRequest, HiddenResponse*>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
|
||||||
|
var execution = ExecuteGenerator(
|
||||||
|
source,
|
||||||
|
allowUnsafe: true);
|
||||||
|
var generatedCompilationErrors = execution.GeneratedCompilationDiagnostics
|
||||||
|
.Where(static diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)
|
||||||
|
.ToArray();
|
||||||
|
var generatorErrors = execution.GeneratorDiagnostics
|
||||||
|
.Where(static diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(generatedCompilationErrors, Is.Empty);
|
||||||
|
Assert.That(generatorErrors, Is.Empty);
|
||||||
|
Assert.That(execution.GeneratedSources, Has.Length.EqualTo(1));
|
||||||
|
Assert.That(execution.GeneratedSources[0].filename, Is.EqualTo("CqrsHandlerRegistry.g.cs"));
|
||||||
|
Assert.That(execution.GeneratedSources[0].content, Is.EqualTo(HiddenPointerResponseExpected));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 验证同一个 implementation 同时包含可直接注册接口与需精确重建接口时,
|
/// 验证同一个 implementation 同时包含可直接注册接口与需精确重建接口时,
|
||||||
/// 生成器会保留两类注册,并继续按 handler interface 名称稳定排序。
|
/// 生成器会保留两类注册,并继续按 handler interface 名称稳定排序。
|
||||||
@ -1232,9 +1363,9 @@ public class CqrsHandlerRegistryGeneratorTests
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe sealed record HiddenRequest() : IRequest<HiddenResponse*>;
|
private unsafe sealed record HiddenRequest() : IRequest<delegate* unmanaged<HiddenResponse>>;
|
||||||
|
|
||||||
public unsafe sealed class HiddenHandler : IRequestHandler<HiddenRequest, HiddenResponse*>
|
public unsafe sealed class HiddenHandler : IRequestHandler<HiddenRequest, delegate* unmanaged<HiddenResponse>>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1341,15 +1472,15 @@ public class CqrsHandlerRegistryGeneratorTests
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe sealed record AlphaRequest() : IRequest<AlphaResponse*>;
|
private unsafe sealed record AlphaRequest() : IRequest<delegate* unmanaged<AlphaResponse>>;
|
||||||
|
|
||||||
private unsafe sealed record BetaRequest() : IRequest<BetaResponse*>;
|
private unsafe sealed record BetaRequest() : IRequest<delegate* unmanaged<BetaResponse>>;
|
||||||
|
|
||||||
public unsafe sealed class BetaHandler : IRequestHandler<BetaRequest, BetaResponse*>
|
public unsafe sealed class BetaHandler : IRequestHandler<BetaRequest, delegate* unmanaged<BetaResponse>>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe sealed class AlphaHandler : IRequestHandler<AlphaRequest, AlphaResponse*>
|
public unsafe sealed class AlphaHandler : IRequestHandler<AlphaRequest, delegate* unmanaged<AlphaResponse>>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,12 +7,14 @@ CQRS 迁移与收敛。
|
|||||||
|
|
||||||
## 当前恢复点
|
## 当前恢复点
|
||||||
|
|
||||||
- 恢复点编号:`CQRS-REWRITE-RP-046`
|
- 恢复点编号:`CQRS-REWRITE-RP-047`
|
||||||
- 当前阶段:`Phase 8`
|
- 当前阶段:`Phase 8`
|
||||||
- 当前焦点:
|
- 当前焦点:
|
||||||
- 当前功能历史已归档,active 跟踪仅保留 `Phase 8` 主线的恢复入口
|
- 当前功能历史已归档,active 跟踪仅保留 `Phase 8` 主线的恢复入口
|
||||||
- 已完成 generated registry 激活路径收敛:`CqrsHandlerRegistrar` 现优先复用缓存工厂委托,避免重复 `ConstructorInfo.Invoke`
|
- 已完成 generated registry 激活路径收敛:`CqrsHandlerRegistrar` 现优先复用缓存工厂委托,避免重复 `ConstructorInfo.Invoke`
|
||||||
- 已补充私有无参构造 generated registry 的回归测试,确保兼容现有生成器产物
|
- 已补充私有无参构造 generated registry 的回归测试,确保兼容现有生成器产物
|
||||||
|
- 已补充 pointer 响应类型的 precise runtime type 生成,避免这类 handler 再退回程序集级 reflection fallback
|
||||||
|
- 已收紧 function pointer 签名的可直接生成判定,仅在其返回值与参数类型都可安全引用时才走静态注册路径
|
||||||
- 中期上继续 `Phase 8` 主线:参考 `ai-libs/Mediator`,继续扩大 generator 覆盖,并选择下一个收益明确的 dispatch / invoker 反射收敛点
|
- 中期上继续 `Phase 8` 主线:参考 `ai-libs/Mediator`,继续扩大 generator 覆盖,并选择下一个收益明确的 dispatch / invoker 反射收敛点
|
||||||
|
|
||||||
## 当前状态摘要
|
## 当前状态摘要
|
||||||
@ -34,6 +36,10 @@ CQRS 迁移与收敛。
|
|||||||
- generated registry 类型首次分析后,会缓存一个可复用的激活工厂,而不是在后续容器注册时重复走 `ConstructorInfo.Invoke`
|
- generated registry 类型首次分析后,会缓存一个可复用的激活工厂,而不是在后续容器注册时重复走 `ConstructorInfo.Invoke`
|
||||||
- 若运行环境不允许动态方法,仍保留原有的反射激活回退,避免阻塞 generated registry 路径
|
- 若运行环境不允许动态方法,仍保留原有的反射激活回退,避免阻塞 generated registry 路径
|
||||||
- `GFramework.Cqrs.Tests` 已补充“私有无参构造 registry 仍可激活”的回归覆盖
|
- `GFramework.Cqrs.Tests` 已补充“私有无参构造 registry 仍可激活”的回归覆盖
|
||||||
|
- `2026-04-20` 已完成一轮 generator 覆盖面扩展:
|
||||||
|
- `CqrsHandlerRegistryGenerator` 现可为 pointer 类型递归重建 runtime type,并通过 `MakePointerType()` 生成精确 service type
|
||||||
|
- function pointer 签名不再默认视为“可直接引用”;只有当返回值与每个参数类型都可从 generated registry 安全引用时,才允许直接生成
|
||||||
|
- 含隐藏类型的 function pointer handler 仍会保留原有 fallback / 诊断路径,避免此次覆盖扩展误伤已有回退边界
|
||||||
- 当前主线优先级:
|
- 当前主线优先级:
|
||||||
- generator 覆盖面继续扩大
|
- generator 覆盖面继续扩大
|
||||||
- dispatch/invoker 反射占比继续下降
|
- dispatch/invoker 反射占比继续下降
|
||||||
@ -58,9 +64,12 @@ CQRS 迁移与收敛。
|
|||||||
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-restore -p:RestoreFallbackFolders= -m:1 -nodeReuse:false`
|
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-restore -p:RestoreFallbackFolders= -m:1 -nodeReuse:false`
|
||||||
- 结果:通过
|
- 结果:通过
|
||||||
- 备注:`63/63` 测试通过;当前沙箱限制了 MSBuild named pipe,验证需在提权环境下运行
|
- 备注:`63/63` 测试通过;当前沙箱限制了 MSBuild named pipe,验证需在提权环境下运行
|
||||||
|
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --no-restore -p:RestoreFallbackFolders= -m:1 -nodeReuse:false --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
|
||||||
|
- 结果:通过
|
||||||
|
- 备注:`14/14` 测试通过;本轮覆盖 pointer precise registration 与 function pointer fallback 边界
|
||||||
|
|
||||||
## 下一步
|
## 下一步
|
||||||
|
|
||||||
1. 继续 `Phase 8` 主线,优先选择下一个收益明确的 dispatch / invoker 反射收敛点继续推进
|
1. 继续 `Phase 8` 主线,优先再找一个收益明确的 generator 覆盖缺口或 dispatch / invoker 反射收敛点继续推进
|
||||||
2. 若继续文档主线,优先再扫 `docs/zh-CN/api-reference` 与教程入口页,补齐仍过时的 CQRS API / 命名空间表述
|
2. 若继续文档主线,优先再扫 `docs/zh-CN/api-reference` 与教程入口页,补齐仍过时的 CQRS API / 命名空间表述
|
||||||
3. 若后续再出现新的 PR review 或 review thread 变化,再重新执行 `$gframework-pr-review` 作为独立验证步骤
|
3. 若后续再出现新的 PR review 或 review thread 变化,再重新执行 `$gframework-pr-review` 作为独立验证步骤
|
||||||
|
|||||||
@ -2,6 +2,18 @@
|
|||||||
|
|
||||||
## 2026-04-20
|
## 2026-04-20
|
||||||
|
|
||||||
|
### 阶段:pointer precise runtime type 覆盖扩展(CQRS-REWRITE-RP-047)
|
||||||
|
|
||||||
|
- 已在 `CqrsHandlerRegistryGenerator` 中补充 pointer 类型的 runtime type 递归建模与源码发射,precise registration 现可通过 `MakePointerType()` 还原隐藏 pointer 响应类型
|
||||||
|
- 已同步收紧 function pointer 签名的可直接生成判定,只有当签名中的返回值与参数类型均可从 generated registry 安全引用时才走静态注册
|
||||||
|
- 已保留含隐藏类型 function pointer handler 的 fallback / 诊断回归覆盖,确保 pointer 支持扩展不会误删原有程序集级 fallback 契约边界
|
||||||
|
- 定向验证与 `CqrsHandlerRegistryGeneratorTests` 全组验证均已通过:
|
||||||
|
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --no-restore -p:RestoreFallbackFolders= -m:1 -nodeReuse:false --filter "FullyQualifiedName~Generates_Precise_Service_Type_For_Hidden_Pointer_Response|FullyQualifiedName~Reports_Diagnostic_And_Skips_Registry_When_Fallback_Metadata_Is_Required_But_Runtime_Contract_Lacks_Fallback_Attribute|FullyQualifiedName~Emits_Assembly_Level_Fallback_Metadata_When_Fallback_Is_Required_And_Runtime_Contract_Is_Available"`
|
||||||
|
- `3/3` passed
|
||||||
|
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --no-restore -p:RestoreFallbackFolders= -m:1 -nodeReuse:false --filter "FullyQualifiedName~CqrsHandlerRegistryGeneratorTests"`
|
||||||
|
- `14/14` passed
|
||||||
|
- 当前沙箱限制 MSBuild named pipe,因此验证在提权环境下执行
|
||||||
|
|
||||||
### 阶段:generated registry 激活反射收敛(CQRS-REWRITE-RP-046)
|
### 阶段:generated registry 激活反射收敛(CQRS-REWRITE-RP-046)
|
||||||
|
|
||||||
- 已在 `CqrsHandlerRegistrar` 中将 generated registry 的无参构造激活改为类型级缓存工厂
|
- 已在 `CqrsHandlerRegistrar` 中将 generated registry 的无参构造激活改为类型级缓存工厂
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user