namespace GFramework.Cqrs.SourceGenerators.Cqrs;
///
/// 为当前编译程序集生成 CQRS 处理器注册器,以减少运行时的程序集反射扫描成本。
///
public sealed partial class CqrsHandlerRegistryGenerator
{
///
/// 生成程序集级 CQRS handler 注册器源码。
///
///
/// 已整理并排序的 handler 注册描述。方法会据此生成 CqrsHandlerRegistry.g.cs,其中包含直接注册、实现类型反射注册、精确运行时类型查找等分支。
///
///
/// 当前轮次选定的程序集级 reflection fallback 元数据发射策略。
/// 调用方必须先确保:若该策略包含 fallback handlers,则当前 runtime 已声明支持对应的 fallback attribute 契约;
/// 否则应在进入本方法前报告诊断并放弃生成,而不是输出会静默漏注册的半成品注册器。
///
/// 完整的注册器源代码文本。
///
/// 当 不包含任何 fallback handlers 时,
/// 输出只包含程序集级 CqrsHandlerRegistryAttribute 和注册器实现。
/// 当其包含 fallback handlers 且 runtime 合同可用时,输出还会附带一个或多个程序集级
/// CqrsReflectionFallbackAttribute,让运行时补齐生成阶段无法精确表达的剩余 handler。
/// 该方法本身不报告诊断;“fallback 必需但 runtime 契约缺失”的错误由调用方在进入本方法前处理。
///
private static string GenerateSource(
GenerationEnvironment generationEnvironment,
IReadOnlyList registrations,
ReflectionFallbackEmissionSpec reflectionFallbackEmission)
{
var sourceShape = CreateGeneratedRegistrySourceShape(generationEnvironment, registrations);
var builder = new StringBuilder();
AppendGeneratedSourcePreamble(builder, reflectionFallbackEmission);
AppendGeneratedRegistryType(builder, registrations, sourceShape);
return builder.ToString();
}
///
/// 预先计算生成注册器需要的辅助分支,让主源码发射流程保持线性且避免重复扫描注册集合。
///
/// 已整理并排序的 handler 注册描述。
/// 当前生成输出需要启用的结构分支。
private static GeneratedRegistrySourceShape CreateGeneratedRegistrySourceShape(
GenerationEnvironment generationEnvironment,
IReadOnlyList registrations)
{
var hasReflectedImplementationRegistrations = registrations.Any(static registration =>
!registration.ReflectedImplementationRegistrations.IsDefaultOrEmpty);
var hasPreciseReflectedRegistrations = registrations.Any(static registration =>
!registration.PreciseReflectedRegistrations.IsDefaultOrEmpty);
var hasReflectionTypeLookups = registrations.Any(static registration =>
!string.IsNullOrWhiteSpace(registration.ReflectionTypeMetadataName));
var hasExternalAssemblyTypeLookups = registrations.Any(static registration =>
registration.PreciseReflectedRegistrations.Any(static preciseRegistration =>
preciseRegistration.ServiceTypeArguments.Any(ContainsExternalAssemblyTypeLookup)));
var requestInvokerEmissions = CreateRequestInvokerEmissions(
generationEnvironment.SupportsRequestInvokerProvider,
registrations);
return new GeneratedRegistrySourceShape(
hasReflectedImplementationRegistrations,
hasPreciseReflectedRegistrations,
hasReflectionTypeLookups,
hasExternalAssemblyTypeLookups,
generationEnvironment.SupportsRequestInvokerProvider,
requestInvokerEmissions);
}
private static ImmutableArray CreateRequestInvokerEmissions(
bool supportsRequestInvokerProvider,
IReadOnlyList registrations)
{
if (!supportsRequestInvokerProvider)
return ImmutableArray.Empty;
var builder = ImmutableArray.CreateBuilder();
var methodIndex = 0;
foreach (var registration in registrations)
{
foreach (var directRegistration in registration.DirectRegistrations)
{
if (directRegistration.RequestInvokerRegistration is not { } requestInvokerRegistration)
continue;
builder.Add(new RequestInvokerEmissionSpec(
requestInvokerRegistration.RequestTypeDisplayName,
requestInvokerRegistration.ResponseTypeDisplayName,
directRegistration.HandlerInterfaceDisplayName,
methodIndex++));
}
}
return builder.ToImmutable();
}
///
/// 发射生成文件头、nullable 指令以及注册器所需的程序集级元数据特性。
///
/// 生成源码构造器。
/// 需要写入程序集级 reflection fallback 特性的元数据策略。
private static void AppendGeneratedSourcePreamble(
StringBuilder builder,
ReflectionFallbackEmissionSpec reflectionFallbackEmission)
{
builder.AppendLine("// ");
builder.AppendLine("#nullable enable");
builder.AppendLine();
if (reflectionFallbackEmission.HasFallbackHandlers)
{
AppendReflectionFallbackAttributes(builder, reflectionFallbackEmission);
builder.AppendLine();
}
builder.Append("[assembly: global::");
builder.Append(CqrsRuntimeNamespace);
builder.Append(".CqrsHandlerRegistryAttribute(typeof(global::");
builder.Append(GeneratedNamespace);
builder.Append('.');
builder.Append(GeneratedTypeName);
builder.AppendLine("))]");
}
///
/// 发射程序集级 reflection fallback 元数据特性,供运行时补齐生成阶段无法精确表达的 handler。
///
/// 生成源码构造器。
/// 需要写入特性的 fallback 元数据策略。
private static void AppendReflectionFallbackAttributes(
StringBuilder builder,
ReflectionFallbackEmissionSpec reflectionFallbackEmission)
{
for (var index = 0; index < reflectionFallbackEmission.Attributes.Length; index++)
{
if (index > 0)
{
builder.AppendLine();
}
AppendReflectionFallbackAttribute(builder, reflectionFallbackEmission.Attributes[index]);
}
}
///
/// 发射单个程序集级 reflection fallback 元数据特性实例。
///
private static void AppendReflectionFallbackAttribute(
StringBuilder builder,
ReflectionFallbackAttributeEmissionSpec attributeEmission)
{
builder.Append("[assembly: global::");
builder.Append(CqrsRuntimeNamespace);
builder.Append(".CqrsReflectionFallbackAttribute(");
for (var index = 0; index < attributeEmission.Values.Length; index++)
{
if (index > 0)
builder.Append(", ");
if (attributeEmission.EmitDirectTypeReferences)
{
builder.Append("typeof(");
builder.Append(attributeEmission.Values[index]);
builder.Append(')');
}
else
{
builder.Append('"');
builder.Append(EscapeStringLiteral(attributeEmission.Values[index]));
builder.Append('"');
}
}
builder.Append(")]");
}
///
/// 发射生成注册器类型本体,包括 Register 方法和运行时反射辅助方法。
///
/// 生成源码构造器。
/// 已排序的 handler 注册描述。
/// 当前输出需要启用的结构分支。
private static void AppendGeneratedRegistryType(
StringBuilder builder,
IReadOnlyList registrations,
GeneratedRegistrySourceShape sourceShape)
{
builder.AppendLine();
builder.Append("namespace ");
builder.Append(GeneratedNamespace);
builder.AppendLine(";");
builder.AppendLine();
builder.Append("internal sealed class ");
builder.Append(GeneratedTypeName);
builder.Append(" : global::");
builder.Append(CqrsRuntimeNamespace);
builder.Append(".ICqrsHandlerRegistry");
if (sourceShape.HasRequestInvokerProvider)
{
builder.Append(", global::");
builder.Append(CqrsRuntimeNamespace);
builder.Append(".ICqrsRequestInvokerProvider, global::");
builder.Append(CqrsRuntimeNamespace);
builder.Append(".IEnumeratesCqrsRequestInvokerDescriptors");
}
builder.AppendLine();
builder.AppendLine("{");
AppendRegisterMethod(builder, registrations, sourceShape);
if (sourceShape.HasRequestInvokerProvider)
{
builder.AppendLine();
AppendRequestInvokerProviderMembers(builder, sourceShape.RequestInvokerEmissions);
}
if (sourceShape.HasExternalAssemblyTypeLookups)
{
builder.AppendLine();
AppendReflectionHelpers(builder);
}
builder.AppendLine("}");
}
///
/// 发射注册器的 Register 方法,保持直接注册和反射注册之间的原始稳定排序。
///
/// 生成源码构造器。
/// 已排序的 handler 注册描述。
/// 当前输出需要启用的结构分支。
private static void AppendRegisterMethod(
StringBuilder builder,
IReadOnlyList registrations,
GeneratedRegistrySourceShape sourceShape)
{
builder.Append(
" public void Register(global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, global::");
builder.Append(LoggingNamespace);
builder.AppendLine(".ILogger logger)");
builder.AppendLine(" {");
builder.AppendLine(" if (services is null)");
builder.AppendLine(" throw new global::System.ArgumentNullException(nameof(services));");
builder.AppendLine(" if (logger is null)");
builder.AppendLine(" throw new global::System.ArgumentNullException(nameof(logger));");
if (sourceShape.RequiresRegistryAssemblyVariable)
{
builder.AppendLine();
builder.Append(" var registryAssembly = typeof(global::");
builder.Append(GeneratedNamespace);
builder.Append('.');
builder.Append(GeneratedTypeName);
builder.AppendLine(").Assembly;");
}
if (registrations.Count > 0)
builder.AppendLine();
for (var registrationIndex = 0; registrationIndex < registrations.Count; registrationIndex++)
{
var registration = registrations[registrationIndex];
if (!registration.ReflectedImplementationRegistrations.IsDefaultOrEmpty ||
!registration.PreciseReflectedRegistrations.IsDefaultOrEmpty)
{
AppendOrderedImplementationRegistrations(builder, registration, registrationIndex);
}
else if (!registration.DirectRegistrations.IsDefaultOrEmpty)
{
AppendDirectRegistrations(builder, registration);
}
}
builder.AppendLine(" }");
}
private static void AppendRequestInvokerProviderMembers(
StringBuilder builder,
ImmutableArray requestInvokerEmissions)
{
AppendRequestInvokerDescriptorArray(builder, requestInvokerEmissions);
builder.AppendLine();
AppendRequestInvokerProviderMethods(builder);
for (var index = 0; index < requestInvokerEmissions.Length; index++)
{
builder.AppendLine();
AppendRequestInvokerMethod(builder, requestInvokerEmissions[index]);
}
}
private static void AppendRequestInvokerDescriptorArray(
StringBuilder builder,
ImmutableArray requestInvokerEmissions)
{
builder.AppendLine(" private static readonly global::GFramework.Cqrs.CqrsRequestInvokerDescriptorEntry[] RequestInvokerDescriptors =");
builder.AppendLine(" [");
for (var index = 0; index < requestInvokerEmissions.Length; index++)
{
var emission = requestInvokerEmissions[index];
builder.Append(" new global::");
builder.Append(CqrsRuntimeNamespace);
builder.Append(".CqrsRequestInvokerDescriptorEntry(typeof(");
builder.Append(emission.RequestTypeDisplayName);
builder.Append("), typeof(");
builder.Append(emission.ResponseTypeDisplayName);
builder.Append("), new global::");
builder.Append(CqrsRuntimeNamespace);
builder.Append(".CqrsRequestInvokerDescriptor(typeof(");
builder.Append(emission.HandlerInterfaceDisplayName);
builder.Append("), typeof(");
builder.Append(GeneratedTypeName);
builder.Append(").GetMethod(nameof(InvokeRequestHandler");
builder.Append(emission.MethodIndex);
builder.Append("), global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Static)!))");
builder.AppendLine(index == requestInvokerEmissions.Length - 1 ? string.Empty : ",");
}
builder.AppendLine(" ];");
}
private static void AppendRequestInvokerProviderMethods(StringBuilder builder)
{
builder.Append(" public global::System.Collections.Generic.IReadOnlyList GetDescriptors()");
builder.AppendLine(" {");
builder.AppendLine(" return RequestInvokerDescriptors;");
builder.AppendLine(" }");
builder.AppendLine();
builder.Append(" public bool TryGetDescriptor(global::System.Type requestType, global::System.Type responseType, out global::");
builder.Append(CqrsRuntimeNamespace);
builder.AppendLine(".CqrsRequestInvokerDescriptor? descriptor)");
builder.AppendLine(" {");
builder.AppendLine(" if (requestType is null)");
builder.AppendLine(" throw new global::System.ArgumentNullException(nameof(requestType));");
builder.AppendLine(" if (responseType is null)");
builder.AppendLine(" throw new global::System.ArgumentNullException(nameof(responseType));");
builder.AppendLine();
builder.AppendLine(" foreach (var entry in RequestInvokerDescriptors)");
builder.AppendLine(" {");
builder.AppendLine(" if (entry.RequestType == requestType && entry.ResponseType == responseType)");
builder.AppendLine(" {");
builder.AppendLine(" descriptor = entry.Descriptor;");
builder.AppendLine(" return true;");
builder.AppendLine(" }");
builder.AppendLine(" }");
builder.AppendLine();
builder.AppendLine(" descriptor = null;");
builder.AppendLine(" return false;");
builder.AppendLine(" }");
}
private static void AppendRequestInvokerMethod(StringBuilder builder, RequestInvokerEmissionSpec emission)
{
builder.Append(" private static global::System.Threading.Tasks.ValueTask<");
builder.Append(emission.ResponseTypeDisplayName);
builder.Append("> InvokeRequestHandler");
builder.Append(emission.MethodIndex);
builder.Append("(object handler, object request, global::System.Threading.CancellationToken cancellationToken)");
builder.AppendLine();
builder.AppendLine(" {");
builder.Append(" var typedHandler = (");
builder.Append(emission.HandlerInterfaceDisplayName);
builder.AppendLine(")handler;");
builder.Append(" var typedRequest = (");
builder.Append(emission.RequestTypeDisplayName);
builder.AppendLine(")request;");
builder.AppendLine(" return typedHandler.Handle(typedRequest, cancellationToken);");
builder.AppendLine(" }");
}
private static void AppendDirectRegistrations(
StringBuilder builder,
ImplementationRegistrationSpec registration)
{
foreach (var directRegistration in registration.DirectRegistrations)
{
AppendServiceRegistration(
builder,
$"typeof({directRegistration.HandlerInterfaceDisplayName})",
$"typeof({directRegistration.ImplementationTypeDisplayName})",
" ");
AppendRegistrationLog(
builder,
directRegistration.ImplementationLogName,
directRegistration.HandlerInterfaceLogName,
" ");
}
}
///
/// 发射 AddTransient 调用,调用方负责传入已经按当前分支解析好的 service 和 implementation 表达式。
///
/// 生成源码构造器。
/// 生成代码中的服务类型表达式。
/// 生成代码中的实现类型表达式。
/// 当前生成语句的缩进。
private static void AppendServiceRegistration(
StringBuilder builder,
string serviceTypeExpression,
string implementationTypeExpression,
string indent)
{
builder.Append(indent);
builder.AppendLine("global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient(");
builder.Append(indent);
builder.AppendLine(" services,");
builder.Append(indent);
builder.Append(" ");
builder.Append(serviceTypeExpression);
builder.AppendLine(",");
builder.Append(indent);
builder.Append(" ");
builder.Append(implementationTypeExpression);
builder.AppendLine(");");
}
///
/// 发射与注册语句配套的调试日志,保持所有生成注册路径的日志文本完全一致。
///
/// 生成源码构造器。
/// 实现类型日志名。
/// handler 接口日志名。
/// 当前生成语句的缩进。
private static void AppendRegistrationLog(
StringBuilder builder,
string implementationLogName,
string handlerInterfaceLogName,
string indent)
{
builder.Append(indent);
builder.Append("logger.Debug(\"Registered CQRS handler ");
builder.Append(EscapeStringLiteral(implementationLogName));
builder.Append(" as ");
builder.Append(EscapeStringLiteral(handlerInterfaceLogName));
builder.AppendLine(".\");");
}
private static void AppendOrderedImplementationRegistrations(
StringBuilder builder,
ImplementationRegistrationSpec registration,
int registrationIndex)
{
var orderedRegistrations = CreateOrderedRegistrations(registration);
var implementationVariableName = $"implementationType{registrationIndex}";
AppendImplementationTypeVariable(builder, registration, implementationVariableName);
builder.Append(" if (");
builder.Append(implementationVariableName);
builder.AppendLine(" is not null)");
builder.AppendLine(" {");
foreach (var orderedRegistration in orderedRegistrations)
{
AppendOrderedRegistration(
builder,
registration,
orderedRegistration,
registrationIndex,
implementationVariableName);
}
builder.AppendLine(" }");
}
///
/// 合并直接注册、实现类型反射注册和精确反射注册,并按 handler 接口日志名排序以保持生成输出稳定。
///
/// 单个实现类型聚合后的注册描述。
/// 带有来源类型和原始索引的有序注册列表。
private static List CreateOrderedRegistrations(ImplementationRegistrationSpec registration)
{
var orderedRegistrations = new List(
registration.DirectRegistrations.Length +
registration.ReflectedImplementationRegistrations.Length +
registration.PreciseReflectedRegistrations.Length);
for (var directIndex = 0; directIndex < registration.DirectRegistrations.Length; directIndex++)
{
orderedRegistrations.Add(new OrderedRegistrationSpec(
registration.DirectRegistrations[directIndex].HandlerInterfaceLogName,
OrderedRegistrationKind.Direct,
directIndex));
}
for (var reflectedIndex = 0;
reflectedIndex < registration.ReflectedImplementationRegistrations.Length;
reflectedIndex++)
{
orderedRegistrations.Add(new OrderedRegistrationSpec(
registration.ReflectedImplementationRegistrations[reflectedIndex].HandlerInterfaceLogName,
OrderedRegistrationKind.ReflectedImplementation,
reflectedIndex));
}
for (var preciseIndex = 0;
preciseIndex < registration.PreciseReflectedRegistrations.Length;
preciseIndex++)
{
orderedRegistrations.Add(new OrderedRegistrationSpec(
registration.PreciseReflectedRegistrations[preciseIndex].HandlerInterfaceLogName,
OrderedRegistrationKind.PreciseReflected,
preciseIndex));
}
orderedRegistrations.Sort(static (left, right) =>
StringComparer.Ordinal.Compare(left.HandlerInterfaceLogName, right.HandlerInterfaceLogName));
return orderedRegistrations;
}
///
/// 发射实现类型变量。公开类型直接使用 typeof,不可直接引用的实现类型则从当前程序集反射解析。
///
/// 生成源码构造器。
/// 单个实现类型聚合后的注册描述。
/// 生成代码中的实现类型变量名。
private static void AppendImplementationTypeVariable(
StringBuilder builder,
ImplementationRegistrationSpec registration,
string implementationVariableName)
{
if (string.IsNullOrWhiteSpace(registration.ReflectionTypeMetadataName))
{
builder.Append(" var ");
builder.Append(implementationVariableName);
builder.Append(" = typeof(");
builder.Append(registration.ImplementationTypeDisplayName);
builder.AppendLine(");");
}
else
{
builder.Append(" var ");
builder.Append(implementationVariableName);
builder.Append(" = registryAssembly.GetType(\"");
builder.Append(EscapeStringLiteral(registration.ReflectionTypeMetadataName!));
builder.AppendLine("\", throwOnError: false, ignoreCase: false);");
}
}
///
/// 根据注册来源发射单条有序注册,确保混合直接和反射路径时仍按 handler 接口名稳定输出。
///
/// 生成源码构造器。
/// 单个实现类型聚合后的注册描述。
/// 带来源类型和原始索引的排序项。
/// 实现类型在整体注册列表中的索引,用于生成稳定变量名。
/// 生成代码中的实现类型变量名。
private static void AppendOrderedRegistration(
StringBuilder builder,
ImplementationRegistrationSpec registration,
OrderedRegistrationSpec orderedRegistration,
int registrationIndex,
string implementationVariableName)
{
switch (orderedRegistration.Kind)
{
case OrderedRegistrationKind.Direct:
AppendOrderedDirectRegistration(
builder,
registration,
registration.DirectRegistrations[orderedRegistration.Index],
implementationVariableName);
break;
case OrderedRegistrationKind.ReflectedImplementation:
AppendOrderedReflectedImplementationRegistration(
builder,
registration,
registration.ReflectedImplementationRegistrations[orderedRegistration.Index],
implementationVariableName);
break;
case OrderedRegistrationKind.PreciseReflected:
AppendOrderedPreciseReflectedRegistration(
builder,
registration,
registration.PreciseReflectedRegistrations[orderedRegistration.Index],
registrationIndex,
orderedRegistration.Index,
implementationVariableName);
break;
default:
throw new InvalidOperationException(
$"Unsupported ordered CQRS registration kind {orderedRegistration.Kind}.");
}
}
///
/// 发射实现类型已通过变量解析、handler 接口可直接引用的直接注册语句。
///
/// 生成源码构造器。
/// 单个实现类型聚合后的注册描述。
/// 当前直接注册项。
/// 生成代码中的实现类型变量名。
private static void AppendOrderedDirectRegistration(
StringBuilder builder,
ImplementationRegistrationSpec registration,
HandlerRegistrationSpec directRegistration,
string implementationVariableName)
{
AppendServiceRegistration(
builder,
$"typeof({directRegistration.HandlerInterfaceDisplayName})",
implementationVariableName,
" ");
AppendRegistrationLog(
builder,
registration.ImplementationLogName,
directRegistration.HandlerInterfaceLogName,
" ");
}
///
/// 发射实现类型需要反射解析、handler 接口可直接引用的注册语句。
///
/// 生成源码构造器。
/// 单个实现类型聚合后的注册描述。
/// 当前实现类型反射注册项。
/// 生成代码中的实现类型变量名。
private static void AppendOrderedReflectedImplementationRegistration(
StringBuilder builder,
ImplementationRegistrationSpec registration,
ReflectedImplementationRegistrationSpec reflectedRegistration,
string implementationVariableName)
{
AppendServiceRegistration(
builder,
$"typeof({reflectedRegistration.HandlerInterfaceDisplayName})",
implementationVariableName,
" ");
AppendRegistrationLog(
builder,
registration.ImplementationLogName,
reflectedRegistration.HandlerInterfaceLogName,
" ");
}
///
/// 发射 handler 接口需要运行时精确构造的注册语句。
///
/// 生成源码构造器。
/// 单个实现类型聚合后的注册描述。
/// 当前精确反射注册项。
/// 实现类型在整体注册列表中的索引。
/// 当前注册项在原始精确反射注册集合中的索引。
/// 生成代码中的实现类型变量名。
private static void AppendOrderedPreciseReflectedRegistration(
StringBuilder builder,
ImplementationRegistrationSpec registration,
PreciseReflectedRegistrationSpec preciseRegistration,
int registrationIndex,
int orderedRegistrationIndex,
string implementationVariableName)
{
var registrationVariablePrefix = $"serviceType{registrationIndex}_{orderedRegistrationIndex}";
AppendPreciseReflectedTypeResolution(
builder,
preciseRegistration.ServiceTypeArguments,
registrationVariablePrefix,
implementationVariableName,
preciseRegistration.OpenHandlerTypeDisplayName,
registration.ImplementationLogName,
preciseRegistration.HandlerInterfaceLogName,
3);
}
private static void AppendPreciseReflectedTypeResolution(
StringBuilder builder,
ImmutableArray serviceTypeArguments,
string registrationVariablePrefix,
string implementationVariableName,
string openHandlerTypeDisplayName,
string implementationLogName,
string handlerInterfaceLogName,
int indentLevel)
{
var indent = new string(' ', indentLevel * 4);
var reflectedArgumentNames = new List();
var resolvedArgumentNames = AppendServiceTypeArgumentResolutions(
builder,
serviceTypeArguments,
registrationVariablePrefix,
reflectedArgumentNames,
indent);
if (reflectedArgumentNames.Count > 0)
indent = AppendReflectedArgumentGuardStart(builder, reflectedArgumentNames, indent);
AppendClosedGenericServiceTypeCreation(
builder,
registrationVariablePrefix,
openHandlerTypeDisplayName,
resolvedArgumentNames,
indent);
AppendServiceRegistration(builder, registrationVariablePrefix, implementationVariableName, indent);
AppendRegistrationLog(builder, implementationLogName, handlerInterfaceLogName, indent);
if (reflectedArgumentNames.Count > 0)
{
builder.Append(new string(' ', indentLevel * 4));
builder.AppendLine("}");
}
}
///
/// 递归发射每个 handler 泛型实参的运行时类型解析表达式。
///
/// 生成源码构造器。
/// handler 服务类型的运行时泛型实参描述。
/// 当前注册项的稳定变量名前缀。
/// 需要空值检查的反射解析变量集合。
/// 当前生成语句的缩进。
/// 可传给 MakeGenericType 的实参表达式。
private static string[] AppendServiceTypeArgumentResolutions(
StringBuilder builder,
ImmutableArray serviceTypeArguments,
string registrationVariablePrefix,
ICollection reflectedArgumentNames,
string indent)
{
var resolvedArgumentNames = new string[serviceTypeArguments.Length];
for (var argumentIndex = 0; argumentIndex < serviceTypeArguments.Length; argumentIndex++)
{
resolvedArgumentNames[argumentIndex] = AppendRuntimeTypeReferenceResolution(
builder,
serviceTypeArguments[argumentIndex],
$"{registrationVariablePrefix}Argument{argumentIndex}",
reflectedArgumentNames,
indent);
}
return resolvedArgumentNames;
}
///
/// 为运行时反射解析出的泛型实参发射空值保护块,避免生成注册器注册无法完整构造的服务类型。
///
/// 生成源码构造器。
/// 需要参与空值检查的变量名。
/// 保护块开始前的缩进。
/// 保护块内部应使用的下一层缩进。
private static string AppendReflectedArgumentGuardStart(
StringBuilder builder,
IReadOnlyList reflectedArgumentNames,
string indent)
{
builder.Append(indent);
builder.Append("if (");
for (var index = 0; index < reflectedArgumentNames.Count; index++)
{
if (index > 0)
builder.Append(" && ");
builder.Append(reflectedArgumentNames[index]);
builder.Append(" is not null");
}
builder.AppendLine(")");
builder.Append(indent);
builder.AppendLine("{");
return $"{indent} ";
}
///
/// 发射关闭 handler 服务类型的 MakeGenericType 构造语句。
///
/// 生成源码构造器。
/// 生成代码中的服务类型变量名。
/// 开放 handler 接口类型显示名。
/// 已解析的泛型实参表达式。
/// 当前生成语句的缩进。
private static void AppendClosedGenericServiceTypeCreation(
StringBuilder builder,
string registrationVariablePrefix,
string openHandlerTypeDisplayName,
IReadOnlyList resolvedArgumentNames,
string indent)
{
builder.Append(indent);
builder.Append("var ");
builder.Append(registrationVariablePrefix);
builder.Append(" = typeof(");
builder.Append(openHandlerTypeDisplayName);
builder.Append(").MakeGenericType(");
for (var index = 0; index < resolvedArgumentNames.Count; index++)
{
if (index > 0)
builder.Append(", ");
builder.Append(resolvedArgumentNames[index]);
}
builder.AppendLine(");");
}
private static string AppendRuntimeTypeReferenceResolution(
StringBuilder builder,
RuntimeTypeReferenceSpec runtimeTypeReference,
string variableBaseName,
ICollection reflectedArgumentNames,
string indent)
{
if (!string.IsNullOrWhiteSpace(runtimeTypeReference.TypeDisplayName))
return $"typeof({runtimeTypeReference.TypeDisplayName})";
if (runtimeTypeReference.ArrayElementTypeReference is not null)
return AppendArrayRuntimeTypeReferenceResolution(
builder,
runtimeTypeReference,
variableBaseName,
reflectedArgumentNames,
indent);
if (runtimeTypeReference.GenericTypeDefinitionReference is not null)
return AppendConstructedGenericRuntimeTypeReferenceResolution(
builder,
runtimeTypeReference,
variableBaseName,
reflectedArgumentNames,
indent);
return AppendReflectionRuntimeTypeReferenceResolution(
builder,
runtimeTypeReference,
variableBaseName,
reflectedArgumentNames,
indent);
}
///
/// 发射数组类型引用的运行时重建表达式。
///
/// 生成源码构造器。
/// 数组类型引用描述。
/// 用于递归生成变量名的稳定前缀。
/// 需要空值检查的反射解析变量集合。
/// 当前生成语句的缩进。
/// 数组类型表达式。
private static string AppendArrayRuntimeTypeReferenceResolution(
StringBuilder builder,
RuntimeTypeReferenceSpec runtimeTypeReference,
string variableBaseName,
ICollection reflectedArgumentNames,
string indent)
{
var elementExpression = AppendRuntimeTypeReferenceResolution(
builder,
runtimeTypeReference.ArrayElementTypeReference!,
$"{variableBaseName}Element",
reflectedArgumentNames,
indent);
return runtimeTypeReference.ArrayRank == 1
? $"{elementExpression}.MakeArrayType()"
: $"{elementExpression}.MakeArrayType({runtimeTypeReference.ArrayRank})";
}
///
/// 发射已构造泛型类型引用的运行时重建表达式。
///
/// 生成源码构造器。
/// 已构造泛型类型引用描述。
/// 用于递归生成变量名的稳定前缀。
/// 需要空值检查的反射解析变量集合。
/// 当前生成语句的缩进。
/// 已构造泛型类型表达式。
private static string AppendConstructedGenericRuntimeTypeReferenceResolution(
StringBuilder builder,
RuntimeTypeReferenceSpec runtimeTypeReference,
string variableBaseName,
ICollection reflectedArgumentNames,
string indent)
{
var genericTypeDefinitionExpression = AppendRuntimeTypeReferenceResolution(
builder,
runtimeTypeReference.GenericTypeDefinitionReference!,
$"{variableBaseName}GenericDefinition",
reflectedArgumentNames,
indent);
var genericArgumentExpressions = new string[runtimeTypeReference.GenericTypeArguments.Length];
for (var argumentIndex = 0;
argumentIndex < runtimeTypeReference.GenericTypeArguments.Length;
argumentIndex++)
{
genericArgumentExpressions[argumentIndex] = AppendRuntimeTypeReferenceResolution(
builder,
runtimeTypeReference.GenericTypeArguments[argumentIndex],
$"{variableBaseName}GenericArgument{argumentIndex}",
reflectedArgumentNames,
indent);
}
return $"{genericTypeDefinitionExpression}.MakeGenericType({string.Join(", ", genericArgumentExpressions)})";
}
///
/// 发射命名类型的运行时反射查找语句,并返回后续服务类型构造应引用的变量名。
///
/// 生成源码构造器。
/// 反射查找类型引用描述。
/// 生成代码中的反射变量名。
/// 需要空值检查的反射解析变量集合。
/// 当前生成语句的缩进。
/// 生成代码中的反射变量名。
private static string AppendReflectionRuntimeTypeReferenceResolution(
StringBuilder builder,
RuntimeTypeReferenceSpec runtimeTypeReference,
string variableBaseName,
ICollection reflectedArgumentNames,
string indent)
{
reflectedArgumentNames.Add(variableBaseName);
builder.Append(indent);
builder.Append("var ");
builder.Append(variableBaseName);
if (string.IsNullOrWhiteSpace(runtimeTypeReference.ReflectionAssemblyName))
{
builder.Append(" = registryAssembly.GetType(\"");
builder.Append(EscapeStringLiteral(runtimeTypeReference.ReflectionTypeMetadataName!));
builder.AppendLine("\", throwOnError: false, ignoreCase: false);");
}
else
{
builder.Append(" = ResolveReferencedAssemblyType(\"");
builder.Append(EscapeStringLiteral(runtimeTypeReference.ReflectionAssemblyName!));
builder.Append("\", \"");
builder.Append(EscapeStringLiteral(runtimeTypeReference.ReflectionTypeMetadataName!));
builder.AppendLine("\");");
}
return variableBaseName;
}
private static void AppendReflectionHelpers(StringBuilder builder)
{
builder.AppendLine(
" private static global::System.Type? ResolveReferencedAssemblyType(string assemblyIdentity, string typeMetadataName)");
builder.AppendLine(" {");
builder.AppendLine(" var assembly = ResolveReferencedAssembly(assemblyIdentity);");
builder.AppendLine(
" return assembly?.GetType(typeMetadataName, throwOnError: false, ignoreCase: false);");
builder.AppendLine(" }");
builder.AppendLine();
builder.AppendLine(
" private static global::System.Reflection.Assembly? ResolveReferencedAssembly(string assemblyIdentity)");
builder.AppendLine(" {");
builder.AppendLine(" global::System.Reflection.AssemblyName targetAssemblyName;");
builder.AppendLine(" try");
builder.AppendLine(" {");
builder.AppendLine(
" targetAssemblyName = new global::System.Reflection.AssemblyName(assemblyIdentity);");
builder.AppendLine(" }");
builder.AppendLine(" catch");
builder.AppendLine(" {");
builder.AppendLine(" return null;");
builder.AppendLine(" }");
builder.AppendLine();
builder.AppendLine(
" foreach (var assembly in global::System.AppDomain.CurrentDomain.GetAssemblies())");
builder.AppendLine(" {");
builder.AppendLine(
" if (global::System.Reflection.AssemblyName.ReferenceMatchesDefinition(targetAssemblyName, assembly.GetName()))");
builder.AppendLine(" return assembly;");
builder.AppendLine(" }");
builder.AppendLine();
builder.AppendLine(" try");
builder.AppendLine(" {");
builder.AppendLine(
" return global::System.Reflection.Assembly.Load(targetAssemblyName);");
builder.AppendLine(" }");
builder.AppendLine(" catch");
builder.AppendLine(" {");
builder.AppendLine(" return null;");
builder.AppendLine(" }");
builder.AppendLine(" }");
}
private static string EscapeStringLiteral(string value)
{
return value.Replace("\\", "\\\\")
.Replace("\"", "\\\"")
.Replace("\n", "\\n")
.Replace("\r", "\\r");
}
}