using System.Collections.Immutable;

namespace Dpz.Core.SourceGenerator.Models;

/// <summary>
/// 一个接口与实现类型的最终注册描述。
/// </summary>
internal readonly struct ServiceRegistration
{
    private ServiceRegistration(
        string serviceType,
        string implementationType,
        string implementationNamespace,
        RegistrationKind kind,
        ServiceLifetime lifetime,
        string? baseAddress,
        int timeoutSeconds,
        ImmutableArray<CachedMethod> cachedMethods,
        ImmutableArray<InvalidatedMethod> invalidatedMethods,
        ImmutableArray<InterfaceMethod> interfaceMethods,
        ImmutableArray<InterfaceProperty> interfaceProperties,
        ImmutableArray<InterfaceEvent> interfaceEvents
    )
    {
        ServiceType = serviceType;
        ImplementationType = implementationType;
        ImplementationNamespace = implementationNamespace;
        Kind = kind;
        Lifetime = lifetime;
        BaseAddress = baseAddress;
        TimeoutSeconds = timeoutSeconds;
        CachedMethods = cachedMethods;
        InvalidatedMethods = invalidatedMethods;
        InterfaceMethods = interfaceMethods;
        InterfaceProperties = interfaceProperties;
        InterfaceEvents = interfaceEvents;
    }

    public string ServiceType { get; }

    public string ImplementationType { get; }

    public string ImplementationNamespace { get; }

    public RegistrationKind Kind { get; }

    public ServiceLifetime Lifetime { get; }

    public string? BaseAddress { get; }

    public int TimeoutSeconds { get; }

    public ImmutableArray<CachedMethod> CachedMethods { get; }

    public ImmutableArray<InvalidatedMethod> InvalidatedMethods { get; }

    public ImmutableArray<InterfaceMethod> InterfaceMethods { get; }

    public ImmutableArray<InterfaceProperty> InterfaceProperties { get; }

    public ImmutableArray<InterfaceEvent> InterfaceEvents { get; }

    public string DecoratorName => "GeneratedCached" + GetTypeName(ImplementationType);

    public string DecoratorType => "global::" + ImplementationNamespace + "." + DecoratorName;

    public string DecoratorHintName => DecoratorName + ".g.cs";

    public string CacheMetadataName =>
        "Generated" + GetTypeName(ImplementationType) + "CacheMetadata";

    public string CacheMetadataHintName => CacheMetadataName + ".g.cs";

    /// <summary>
    /// 是否需要为该服务生成缓存装饰器。
    /// </summary>
    /// <remarks>
    /// 显式标记了 <c>[Cache]</c> 或 <c>[InvalidateCache]</c> 的服务需要装饰器。
    /// </remarks>
    public bool RequiresDecorator => CachedMethods.Length > 0 || InvalidatedMethods.Length > 0;

    public static ServiceRegistration Service(
        string serviceType,
        string implementationType,
        string implementationNamespace,
        ServiceLifetime lifetime,
        ImmutableArray<CachedMethod> cachedMethods,
        ImmutableArray<InvalidatedMethod> invalidatedMethods,
        ImmutableArray<InterfaceMethod> interfaceMethods,
        ImmutableArray<InterfaceProperty> interfaceProperties,
        ImmutableArray<InterfaceEvent> interfaceEvents
    )
    {
        return new ServiceRegistration(
            serviceType,
            implementationType,
            implementationNamespace,
            RegistrationKind.Service,
            lifetime,
            null,
            0,
            cachedMethods,
            invalidatedMethods,
            interfaceMethods,
            interfaceProperties,
            interfaceEvents
        );
    }

    public static ServiceRegistration HttpClient(
        string serviceType,
        string implementationType,
        string implementationNamespace,
        string baseAddress,
        int timeoutSeconds,
        ImmutableArray<CachedMethod> cachedMethods,
        ImmutableArray<InvalidatedMethod> invalidatedMethods,
        ImmutableArray<InterfaceMethod> interfaceMethods,
        ImmutableArray<InterfaceProperty> interfaceProperties,
        ImmutableArray<InterfaceEvent> interfaceEvents
    )
    {
        return new ServiceRegistration(
            serviceType,
            implementationType,
            implementationNamespace,
            RegistrationKind.HttpClient,
            ServiceLifetime.Transient,
            baseAddress,
            timeoutSeconds,
            cachedMethods,
            invalidatedMethods,
            interfaceMethods,
            interfaceProperties,
            interfaceEvents
        );
    }

    private static string GetTypeName(string fullyQualifiedTypeName)
    {
        var name = fullyQualifiedTypeName.Replace("global::", string.Empty);
        var index = name.LastIndexOf('.');
        return index >= 0 ? name.Substring(index + 1) : name;
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

代码解释

这是一个C# Source Generator项目中的服务注册描述模型类,用于表示需要生成代码的服务信息。

主要功能

1. 数据结构

ServiceRegistration 是一个不可变的值类型结构体readonly struct),用于存储服务注册的完整信息:

  • 服务类型信息

    • ServiceType: 接口类型
    • ImplementationType: 实现类型
    • ImplementationNamespace: 实现类所在命名空间
  • 注册配置

    • Kind: 注册类型(普通服务/HTTP客户端)
    • Lifetime: 服务生命周期(Singleton/Scoped/Transient)
    • BaseAddress: HTTP客户端的基地址
    • TimeoutSeconds: 超时秒数
  • 接口成员集合(使用不可变数组):

    • CachedMethods: 标记了缓存特性的方法
    • InvalidatedMethods: 标记了缓存失效特性的方法
    • InterfaceMethods: 接口的所有方法
    • InterfaceProperties: 接口的所有属性
    • InterfaceEvents: 接口的所有事件

2. 工厂方法

  • Service(...): 创建普通服务注册,支持指定生命周期
  • HttpClient(...): 创建HTTP客户端注册,固定为Transient生命周期

3. 计算属性

  • DecoratorName: 生成的缓存装饰器类名(如 GeneratedCachedMyService
  • DecoratorType: 装饰器的完全限定类型名
  • DecoratorHintName: 生成的装饰器文件名
  • CacheMetadataName: 缓存元数据类名
  • RequiresDecorator: 判断是否需要生成装饰器(有缓存或失效方法时需要)

4. 辅助方法

  • GetTypeName(...): 从完全限定类型名中提取简短类型名(去除命名空间前缀)

使用场景

这个结构体在Source Generator中用于:

  1. 收集需要自动注册的服务信息
  2. 为带有缓存特性的服务生成装饰器代码
  3. 生成依赖注入配置代码
  4. 生成HTTP客户端配置代码

是典型的不可变数据传输对象(DTO)模式,确保数据在生成过程中的一致性和线程安全性。

评论加载中...