mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-22 10:34:30 +08:00
feat(core): 添加上下文感知扩展方法并完善架构上下文接口
- 新增 ContextAwareExtensions 扩展类,提供便捷的上下文访问方法 - 为 IContextAware 接口添加 GetContext 方法以获取架构上下文 - 更新 ContextAwareBase 基类实现 GetContext 方法 - 改进源代码生成器的 Generate 方法参数结构 - 重构 ContextAwareGenerator 生成器实现接口方法自动实现 - 更新单元测试以验证新生成的上下文感知代码正确性
This commit is contained in:
parent
e808a0c365
commit
02e2e31e95
@ -3,7 +3,7 @@
|
|||||||
namespace GFramework.Core.Abstractions.rule;
|
namespace GFramework.Core.Abstractions.rule;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 上下文感知接口,用于为实现该接口的类提供设置架构上下文的能力
|
/// 上下文感知接口,用于为实现该接口的类提供设置和获取架构上下文的能力
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IContextAware
|
public interface IContextAware
|
||||||
{
|
{
|
||||||
@ -12,4 +12,10 @@ public interface IContextAware
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context">架构上下文对象,用于提供架构级别的服务和功能访问</param>
|
/// <param name="context">架构上下文对象,用于提供架构级别的服务和功能访问</param>
|
||||||
void SetContext(IArchitectureContext context);
|
void SetContext(IArchitectureContext context);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取架构上下文
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>当前的架构上下文对象</returns>
|
||||||
|
IArchitectureContext GetContext();
|
||||||
}
|
}
|
||||||
166
GFramework.Core/extensions/ContextAwareExtensions.cs
Normal file
166
GFramework.Core/extensions/ContextAwareExtensions.cs
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
using GFramework.Core.Abstractions.command;
|
||||||
|
using GFramework.Core.Abstractions.events;
|
||||||
|
using GFramework.Core.Abstractions.model;
|
||||||
|
using GFramework.Core.Abstractions.query;
|
||||||
|
using GFramework.Core.Abstractions.rule;
|
||||||
|
using GFramework.Core.Abstractions.system;
|
||||||
|
using GFramework.Core.Abstractions.utility;
|
||||||
|
|
||||||
|
namespace GFramework.Core.extensions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 提供对 IContextAware 接口的扩展方法
|
||||||
|
/// </summary>
|
||||||
|
public static class ContextAwareExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获取架构上下文中的指定系统
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TSystem">目标系统类型</typeparam>
|
||||||
|
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||||
|
/// <returns>指定类型的系统实例</returns>
|
||||||
|
/// <exception cref="ArgumentNullException">当 contextAware 为 null 时抛出</exception>
|
||||||
|
public static TSystem? GetSystem<TSystem>(this IContextAware contextAware) where TSystem : class, ISystem
|
||||||
|
{
|
||||||
|
if (contextAware == null) throw new ArgumentNullException(nameof(contextAware));
|
||||||
|
var context = contextAware.GetContext();
|
||||||
|
return context.GetSystem<TSystem>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取架构上下文中的指定模型
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TModel">目标模型类型</typeparam>
|
||||||
|
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||||
|
/// <returns>指定类型的模型实例</returns>
|
||||||
|
/// <exception cref="ArgumentNullException">当 contextAware 为 null 时抛出</exception>
|
||||||
|
public static TModel? GetModel<TModel>(this IContextAware contextAware) where TModel : class, IModel
|
||||||
|
{
|
||||||
|
if (contextAware == null) throw new ArgumentNullException(nameof(contextAware));
|
||||||
|
var context = contextAware.GetContext();
|
||||||
|
return context.GetModel<TModel>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取架构上下文中的指定工具
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TUtility">目标工具类型</typeparam>
|
||||||
|
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||||
|
/// <returns>指定类型的工具实例</returns>
|
||||||
|
/// <exception cref="ArgumentNullException">当 contextAware 为 null 时抛出</exception>
|
||||||
|
public static TUtility? GetUtility<TUtility>(this IContextAware contextAware) where TUtility : class, IUtility
|
||||||
|
{
|
||||||
|
if (contextAware == null) throw new ArgumentNullException(nameof(contextAware));
|
||||||
|
var context = contextAware.GetContext();
|
||||||
|
return context.GetUtility<TUtility>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送一个查询请求
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TResult">查询结果类型</typeparam>
|
||||||
|
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||||
|
/// <param name="query">要发送的查询</param>
|
||||||
|
/// <returns>查询结果</returns>
|
||||||
|
/// <exception cref="ArgumentNullException">当 contextAware 或 query 为 null 时抛出</exception>
|
||||||
|
public static TResult SendQuery<TResult>(this IContextAware contextAware, IQuery<TResult> query)
|
||||||
|
{
|
||||||
|
if (contextAware == null) throw new ArgumentNullException(nameof(contextAware));
|
||||||
|
if (query == null) throw new ArgumentNullException(nameof(query));
|
||||||
|
|
||||||
|
var context = contextAware.GetContext();
|
||||||
|
return context.SendQuery(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送一个无返回结果的命令
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||||
|
/// <param name="command">要发送的命令</param>
|
||||||
|
/// <exception cref="ArgumentNullException">当 contextAware 或 command 为 null 时抛出</exception>
|
||||||
|
public static void SendCommand(this IContextAware contextAware, ICommand command)
|
||||||
|
{
|
||||||
|
if (contextAware == null) throw new ArgumentNullException(nameof(contextAware));
|
||||||
|
if (command == null) throw new ArgumentNullException(nameof(command));
|
||||||
|
|
||||||
|
var context = contextAware.GetContext();
|
||||||
|
context.SendCommand(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送一个带返回值的命令
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TResult">命令执行结果类型</typeparam>
|
||||||
|
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||||
|
/// <param name="command">要发送的命令</param>
|
||||||
|
/// <returns>命令执行结果</returns>
|
||||||
|
/// <exception cref="ArgumentNullException">当 contextAware 或 command 为 null 时抛出</exception>
|
||||||
|
public static TResult SendCommand<TResult>(this IContextAware contextAware, ICommand<TResult> command)
|
||||||
|
{
|
||||||
|
if (contextAware == null) throw new ArgumentNullException(nameof(contextAware));
|
||||||
|
if (command == null) throw new ArgumentNullException(nameof(command));
|
||||||
|
|
||||||
|
var context = contextAware.GetContext();
|
||||||
|
return context.SendCommand(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送一个事件
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TEvent">事件类型</typeparam>
|
||||||
|
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||||
|
/// <exception cref="ArgumentNullException">当 contextAware 为 null 时抛出</exception>
|
||||||
|
public static void SendEvent<TEvent>(this IContextAware contextAware) where TEvent : new()
|
||||||
|
{
|
||||||
|
if (contextAware == null) throw new ArgumentNullException(nameof(contextAware));
|
||||||
|
var context = contextAware.GetContext();
|
||||||
|
context.SendEvent<TEvent>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送一个具体的事件实例
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TEvent">事件类型</typeparam>
|
||||||
|
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||||
|
/// <param name="e">事件实例</param>
|
||||||
|
/// <exception cref="ArgumentNullException">当 contextAware 或 e 为 null 时抛出</exception>
|
||||||
|
public static void SendEvent<TEvent>(this IContextAware contextAware, TEvent e) where TEvent : class
|
||||||
|
{
|
||||||
|
if (contextAware == null) throw new ArgumentNullException(nameof(contextAware));
|
||||||
|
if (e == null) throw new ArgumentNullException(nameof(e));
|
||||||
|
|
||||||
|
var context = contextAware.GetContext();
|
||||||
|
context.SendEvent(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 注册事件处理器
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TEvent">事件类型</typeparam>
|
||||||
|
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||||
|
/// <param name="handler">事件处理委托</param>
|
||||||
|
/// <returns>事件注销接口</returns>
|
||||||
|
public static IUnRegister RegisterEvent<TEvent>(this IContextAware contextAware, Action<TEvent> handler)
|
||||||
|
{
|
||||||
|
if (contextAware == null) throw new ArgumentNullException(nameof(contextAware));
|
||||||
|
if (handler == null) throw new ArgumentNullException(nameof(handler));
|
||||||
|
|
||||||
|
var context = contextAware.GetContext();
|
||||||
|
return context.RegisterEvent(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 取消对某类型事件的监听
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TEvent">事件类型</typeparam>
|
||||||
|
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
|
||||||
|
/// <param name="onEvent">之前绑定的事件处理器</param>
|
||||||
|
public static void UnRegisterEvent<TEvent>(this IContextAware contextAware, Action<TEvent> onEvent)
|
||||||
|
{
|
||||||
|
if (contextAware == null) throw new ArgumentNullException(nameof(contextAware));
|
||||||
|
if (onEvent == null) throw new ArgumentNullException(nameof(onEvent));
|
||||||
|
|
||||||
|
var context = contextAware.GetContext();
|
||||||
|
context.UnRegisterEvent(onEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -23,6 +23,15 @@ public abstract class ContextAwareBase : IContextAware
|
|||||||
OnContextReady();
|
OnContextReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取架构上下文
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>当前架构上下文对象</returns>
|
||||||
|
IArchitectureContext IContextAware.GetContext()
|
||||||
|
{
|
||||||
|
return Context;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 当上下文准备就绪时调用的虚方法,子类可以重写此方法来执行上下文相关的初始化逻辑
|
/// 当上下文准备就绪时调用的虚方法,子类可以重写此方法来执行上下文相关的初始化逻辑
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -20,12 +20,18 @@ public sealed class GodotLoggerGenerator : TypeAttributeClassGeneratorBase
|
|||||||
protected override string AttributeShortNameWithoutSuffix => "GodotLog";
|
protected override string AttributeShortNameWithoutSuffix => "GodotLog";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 生成日志字段的源代码
|
/// 生成源代码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="symbol">类符号</param>
|
/// <param name="context">源生产上下文</param>
|
||||||
/// <param name="attr">GodotLogAttribute属性数据</param>
|
/// <param name="compilation">编译对象</param>
|
||||||
|
/// <param name="symbol">命名类型符号</param>
|
||||||
|
/// <param name="attr">属性数据</param>
|
||||||
/// <returns>生成的源代码字符串</returns>
|
/// <returns>生成的源代码字符串</returns>
|
||||||
protected override string Generate(INamedTypeSymbol symbol, AttributeData attr)
|
protected override string Generate(
|
||||||
|
SourceProductionContext context,
|
||||||
|
Compilation compilation,
|
||||||
|
INamedTypeSymbol symbol,
|
||||||
|
AttributeData attr)
|
||||||
{
|
{
|
||||||
var ns = symbol.ContainingNamespace.IsGlobalNamespace
|
var ns = symbol.ContainingNamespace.IsGlobalNamespace
|
||||||
? null
|
? null
|
||||||
|
|||||||
@ -109,7 +109,7 @@ public abstract class AttributeClassGeneratorBase : IIncrementalGenerator
|
|||||||
CommonDiagnostics.Trace(context,
|
CommonDiagnostics.Trace(context,
|
||||||
$"[GEN] Generating source: {hintName}");
|
$"[GEN] Generating source: {hintName}");
|
||||||
|
|
||||||
context.AddSource(hintName, Generate(symbol, attr));
|
context.AddSource(hintName, Generate(context, compilation, symbol, attr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -133,10 +133,14 @@ public abstract class AttributeClassGeneratorBase : IIncrementalGenerator
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 生成源代码
|
/// 生成源代码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="context">源生产上下文</param>
|
||||||
|
/// <param name="compilation">编译对象</param>
|
||||||
/// <param name="symbol">命名类型符号</param>
|
/// <param name="symbol">命名类型符号</param>
|
||||||
/// <param name="attr">属性数据</param>
|
/// <param name="attr">属性数据</param>
|
||||||
/// <returns>生成的源代码字符串</returns>
|
/// <returns>生成的源代码字符串</returns>
|
||||||
protected abstract string Generate(
|
protected abstract string Generate(
|
||||||
|
SourceProductionContext context,
|
||||||
|
Compilation compilation,
|
||||||
INamedTypeSymbol symbol,
|
INamedTypeSymbol symbol,
|
||||||
AttributeData attr);
|
AttributeData attr);
|
||||||
|
|
||||||
|
|||||||
@ -40,6 +40,8 @@ public class ContextAwareGeneratorTests
|
|||||||
{
|
{
|
||||||
void SetContext(
|
void SetContext(
|
||||||
GFramework.Core.Abstractions.architecture.IArchitectureContext context);
|
GFramework.Core.Abstractions.architecture.IArchitectureContext context);
|
||||||
|
|
||||||
|
GFramework.Core.Abstractions.architecture.IArchitectureContext GetContext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,11 +64,17 @@ public class ContextAwareGeneratorTests
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected GFramework.Core.Abstractions.architecture.IArchitectureContext Context { get; private set; } = null!;
|
protected GFramework.Core.Abstractions.architecture.IArchitectureContext Context { get; private set; } = null!;
|
||||||
|
|
||||||
void GFramework.Core.Abstractions.rule.IContextAware.SetContext(
|
void global::GFramework.Core.Abstractions.rule.IContextAware.SetContext(
|
||||||
GFramework.Core.Abstractions.architecture.IArchitectureContext context)
|
global::GFramework.Core.Abstractions.architecture.IArchitectureContext context)
|
||||||
{
|
{
|
||||||
Context = context;
|
Context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
global::GFramework.Core.Abstractions.architecture.IArchitectureContext
|
||||||
|
global::GFramework.Core.Abstractions.rule.IContextAware.GetContext()
|
||||||
|
{
|
||||||
|
return Context;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
""";
|
""";
|
||||||
|
|
||||||
@ -113,6 +121,8 @@ public class ContextAwareGeneratorTests
|
|||||||
{
|
{
|
||||||
void SetContext(
|
void SetContext(
|
||||||
GFramework.Core.Abstractions.architecture.IArchitectureContext context);
|
GFramework.Core.Abstractions.architecture.IArchitectureContext context);
|
||||||
|
|
||||||
|
GFramework.Core.Abstractions.architecture.IArchitectureContext GetContext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,6 +150,12 @@ public class ContextAwareGeneratorTests
|
|||||||
{
|
{
|
||||||
Context = context;
|
Context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GFramework.Core.Abstractions.architecture.IArchitectureContext
|
||||||
|
GFramework.Core.Abstractions.rule.IContextAware.GetContext()
|
||||||
|
{
|
||||||
|
return Context;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
""";
|
""";
|
||||||
|
|
||||||
|
|||||||
@ -41,9 +41,18 @@ public sealed class LoggerGenerator : TypeAttributeClassGeneratorBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 生成 Logger 字段的代码
|
/// 生成源代码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected override string Generate(INamedTypeSymbol symbol, AttributeData attr)
|
/// <param name="context">源生产上下文</param>
|
||||||
|
/// <param name="compilation">编译对象</param>
|
||||||
|
/// <param name="symbol">命名类型符号</param>
|
||||||
|
/// <param name="attr">属性数据</param>
|
||||||
|
/// <returns>生成的源代码字符串</returns>
|
||||||
|
protected override string Generate(
|
||||||
|
SourceProductionContext context,
|
||||||
|
Compilation compilation,
|
||||||
|
INamedTypeSymbol symbol,
|
||||||
|
AttributeData attr)
|
||||||
{
|
{
|
||||||
var ns = symbol.ContainingNamespace.IsGlobalNamespace
|
var ns = symbol.ContainingNamespace.IsGlobalNamespace
|
||||||
? null
|
? null
|
||||||
|
|||||||
@ -11,23 +11,11 @@ namespace GFramework.SourceGenerators.rule;
|
|||||||
[Generator]
|
[Generator]
|
||||||
public sealed class ContextAwareGenerator : MetadataAttributeClassGeneratorBase
|
public sealed class ContextAwareGenerator : MetadataAttributeClassGeneratorBase
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// 获取属性元数据的完整名称,用于标识ContextAwareAttribute的完全限定名
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>返回ContextAwareAttribute的完全限定名字符串</returns>
|
|
||||||
protected override string AttributeMetadataName =>
|
protected override string AttributeMetadataName =>
|
||||||
$"{PathContests.SourceGeneratorsAbstractionsPath}.rule.ContextAwareAttribute";
|
$"{PathContests.SourceGeneratorsAbstractionsPath}.rule.ContextAwareAttribute";
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 仅用于 Syntax 粗筛选
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>返回属性的简短名称,不包含后缀</returns>
|
|
||||||
protected override string AttributeShortNameWithoutSuffix => "ContextAware";
|
protected override string AttributeShortNameWithoutSuffix => "ContextAware";
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 额外语义校验:必须实现 IContextAware
|
|
||||||
/// </summary>
|
|
||||||
protected override bool ValidateSymbol(
|
protected override bool ValidateSymbol(
|
||||||
SourceProductionContext context,
|
SourceProductionContext context,
|
||||||
Compilation compilation,
|
Compilation compilation,
|
||||||
@ -35,9 +23,8 @@ public sealed class ContextAwareGenerator : MetadataAttributeClassGeneratorBase
|
|||||||
INamedTypeSymbol symbol,
|
INamedTypeSymbol symbol,
|
||||||
AttributeData attr)
|
AttributeData attr)
|
||||||
{
|
{
|
||||||
var iContextAware = compilation
|
var iContextAware = compilation.GetTypeByMetadataName(
|
||||||
.GetTypeByMetadataName(
|
$"{PathContests.CoreAbstractionsNamespace}.rule.IContextAware");
|
||||||
$"{PathContests.CoreAbstractionsNamespace}.rule.IContextAware");
|
|
||||||
|
|
||||||
if (iContextAware is null)
|
if (iContextAware is null)
|
||||||
{
|
{
|
||||||
@ -45,7 +32,6 @@ public sealed class ContextAwareGenerator : MetadataAttributeClassGeneratorBase
|
|||||||
ContextAwareDiagnostic.ClassMustImplementIContextAware,
|
ContextAwareDiagnostic.ClassMustImplementIContextAware,
|
||||||
syntax.Identifier.GetLocation(),
|
syntax.Identifier.GetLocation(),
|
||||||
symbol.Name));
|
symbol.Name));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,24 +42,31 @@ public sealed class ContextAwareGenerator : MetadataAttributeClassGeneratorBase
|
|||||||
ContextAwareDiagnostic.ClassMustImplementIContextAware,
|
ContextAwareDiagnostic.ClassMustImplementIContextAware,
|
||||||
syntax.Identifier.GetLocation(),
|
syntax.Identifier.GetLocation(),
|
||||||
symbol.Name));
|
symbol.Name));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 生成源码
|
/// 生成源代码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="context">源生产上下文</param>
|
||||||
|
/// <param name="compilation">编译对象</param>
|
||||||
|
/// <param name="symbol">命名类型符号</param>
|
||||||
|
/// <param name="attr">属性数据</param>
|
||||||
|
/// <returns>生成的源代码字符串</returns>
|
||||||
protected override string Generate(
|
protected override string Generate(
|
||||||
|
SourceProductionContext context,
|
||||||
|
Compilation compilation,
|
||||||
INamedTypeSymbol symbol,
|
INamedTypeSymbol symbol,
|
||||||
AttributeData attr)
|
AttributeData attr)
|
||||||
{
|
{
|
||||||
var ns = symbol.ContainingNamespace.IsGlobalNamespace
|
var ns = symbol.ContainingNamespace.IsGlobalNamespace
|
||||||
? null
|
? null
|
||||||
: symbol.ContainingNamespace.ToDisplayString();
|
: symbol.ContainingNamespace.ToDisplayString();
|
||||||
|
var iContextAware = compilation.GetTypeByMetadataName(
|
||||||
|
$"{PathContests.CoreAbstractionsNamespace}.rule.IContextAware");
|
||||||
|
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
sb.AppendLine("// <auto-generated/>");
|
sb.AppendLine("// <auto-generated/>");
|
||||||
@ -89,36 +82,106 @@ public sealed class ContextAwareGenerator : MetadataAttributeClassGeneratorBase
|
|||||||
sb.AppendLine($"partial class {symbol.Name}");
|
sb.AppendLine($"partial class {symbol.Name}");
|
||||||
sb.AppendLine("{");
|
sb.AppendLine("{");
|
||||||
|
|
||||||
// 属性
|
GenerateContextProperty(sb);
|
||||||
|
GenerateInterfaceImplementations(sb, iContextAware!);
|
||||||
|
|
||||||
|
sb.AppendLine("}");
|
||||||
|
return sb.ToString().TrimEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string GetHintName(INamedTypeSymbol symbol)
|
||||||
|
=> $"{symbol.Name}.ContextAware.g.cs";
|
||||||
|
|
||||||
|
// =========================
|
||||||
|
// 生成 Context 属性
|
||||||
|
// =========================
|
||||||
|
private static void GenerateContextProperty(StringBuilder sb)
|
||||||
|
{
|
||||||
sb.AppendLine(" /// <summary>");
|
sb.AppendLine(" /// <summary>");
|
||||||
sb.AppendLine(" /// 自动注入的架构上下文");
|
sb.AppendLine(" /// 自动注入的架构上下文");
|
||||||
sb.AppendLine(" /// </summary>");
|
sb.AppendLine(" /// </summary>");
|
||||||
sb.AppendLine(
|
sb.AppendLine(
|
||||||
$" protected {PathContests.CoreAbstractionsNamespace}.architecture.IArchitectureContext Context {{ get; private set; }} = null!;");
|
$" protected {PathContests.CoreAbstractionsNamespace}.architecture.IArchitectureContext Context {{ get; private set; }} = null!;");
|
||||||
sb.AppendLine();
|
sb.AppendLine();
|
||||||
|
|
||||||
// 方法
|
|
||||||
sb.AppendLine(
|
|
||||||
$" void {PathContests.CoreAbstractionsNamespace}.rule.IContextAware.SetContext(");
|
|
||||||
sb.AppendLine(
|
|
||||||
$" {PathContests.CoreAbstractionsNamespace}.architecture.IArchitectureContext context)");
|
|
||||||
sb.AppendLine(" {");
|
|
||||||
sb.AppendLine(" Context = context;");
|
|
||||||
sb.AppendLine(" }");
|
|
||||||
|
|
||||||
sb.AppendLine("}");
|
|
||||||
|
|
||||||
return sb.ToString().TrimEnd();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// =========================
|
||||||
/// <summary>
|
// 自动实现接口方法
|
||||||
/// 自定义生成文件名
|
// =========================
|
||||||
/// </summary>
|
private static void GenerateInterfaceImplementations(
|
||||||
protected override string GetHintName(INamedTypeSymbol symbol)
|
StringBuilder sb,
|
||||||
|
INamedTypeSymbol interfaceSymbol)
|
||||||
{
|
{
|
||||||
// 包含命名空间和生成器类名路径
|
var interfaceFullName = interfaceSymbol.ToDisplayString(
|
||||||
return
|
SymbolDisplayFormat.FullyQualifiedFormat);
|
||||||
$"{symbol.Name}.ContextAware.g.cs";
|
|
||||||
|
foreach (var member in interfaceSymbol.GetMembers().OfType<IMethodSymbol>())
|
||||||
|
{
|
||||||
|
if (member.MethodKind != MethodKind.Ordinary)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
GenerateMethod(sb, interfaceFullName, member);
|
||||||
|
sb.AppendLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateMethod(
|
||||||
|
StringBuilder sb,
|
||||||
|
string interfaceFullName,
|
||||||
|
IMethodSymbol method)
|
||||||
|
{
|
||||||
|
var returnType = method.ReturnType.ToDisplayString(
|
||||||
|
SymbolDisplayFormat.FullyQualifiedFormat);
|
||||||
|
|
||||||
|
var parameters = string.Join(", ",
|
||||||
|
method.Parameters.Select(p =>
|
||||||
|
$"{p.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)} {p.Name}"));
|
||||||
|
|
||||||
|
sb.AppendLine(
|
||||||
|
$" {returnType} {interfaceFullName}.{method.Name}({parameters})");
|
||||||
|
|
||||||
|
sb.AppendLine(" {");
|
||||||
|
GenerateMethodBody(sb, method);
|
||||||
|
sb.AppendLine(" }");
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================
|
||||||
|
// 方法语义策略
|
||||||
|
// =========================
|
||||||
|
private static void GenerateMethodBody(
|
||||||
|
StringBuilder sb,
|
||||||
|
IMethodSymbol method)
|
||||||
|
{
|
||||||
|
switch (method.Name)
|
||||||
|
{
|
||||||
|
case "SetContext":
|
||||||
|
sb.AppendLine(" Context = context;");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "GetContext":
|
||||||
|
sb.AppendLine(" return Context;");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
GenerateFallbackBody(sb, method);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateFallbackBody(
|
||||||
|
StringBuilder sb,
|
||||||
|
IMethodSymbol method)
|
||||||
|
{
|
||||||
|
if (method.ReturnsVoid)
|
||||||
|
{
|
||||||
|
sb.AppendLine(" // no-op");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.AppendLine(
|
||||||
|
$" throw new System.NotImplementedException(");
|
||||||
|
sb.AppendLine(
|
||||||
|
$" \"Method '{method.Name}' is not supported by ContextAwareGenerator.\");");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user