如何在编译时实现不同程序集的Aspect之间的数据共享
你描述的直接在CompileTimeInitialize阶段跨程序集传递数据到另一个Aspect单实例的方案是不可行的,PostSharp的编译过程是按程序集独立隔离执行的,不同程序集的编译期Aspect实例生命周期完全独立,仅在当前程序集的编译上下文内生效,这也是你之前验证到仅同程序集内数据共享有效的根本原因。
以下是符合需求的跨程序集编译期数据采集实现方案:
1. 公共程序集预定义基础结构
首先在你确认一定会优先加载的公共程序集中定义两类组件:
- 可序列化的元数据容器:用于存储所有
PersistentId采集的信息(如类型全限定名与ID的映射关系等),必须标记[Serializable]以支持序列化嵌入程序集。 - 程序集级聚合Aspect:定义
PersistentIdRegistryAspect继承自AssemblyLevelAspect,配置[MulticastAttributeUsage(MulticastTargets.Assembly, PersistMetaData = true)],作为全局数据的汇总、存储、暴露入口。
2. 编译期跨程序集数据采集
修改你的PersistentId类型级Aspect的CompileTimeInitialize逻辑:
不再尝试直接修改外部Aspect的单实例,而是将当前采集到的单条数据作为程序集级注解标注到当前被编译的业务程序集上。
在公共程序集的PersistentIdRegistryAspect的CompileTimeInitialize方法中,通过PostSharp提供的项目访问API遍历所有引用了PersistentId依赖的程序集,读取每个程序集上标注的所有PersistentId注解,汇总到之前定义的可序列化元数据容器中。
3. 编译期数据嵌入
重写PersistentIdRegistryAspect的ProvideAspectResources方法,将汇总完成的元数据容器序列化后,作为嵌入资源写入公共程序集。
4. 运行时全局读取
在PersistentIdRegistryAspect的RuntimeInitialize方法中,读取公共程序集的嵌入资源并反序列化为元数据容器,暴露为静态只读单例属性。公共程序集加载时就会完成该初始化流程,早于所有业务程序集的加载逻辑,完全满足你在业务程序集加载前使用采集数据的需求。
内容的提问来源于stack exchange,提问作者crypto_rsa

