Castle Windsor:如何跨不同执行时间的组件图共享临时对象?
解决不同执行时机组件间临时对象共享的方案
嘿,针对你提到的遗留状态引擎(每个IState负责生成下一个状态,会话上下文带GUID,还有静态的CreatedCount/DisposedCount追踪问题),我整理了几个贴合你场景的实用方案:
1. 给会话上下文加个“共享对象仓库”(最适配现有架构)
既然每个状态已经持有会话上下文,那直接把需要共享的临时对象挂载到上下文里就好,完全不用改动现有状态流转的核心逻辑:
- 扩展你的
SessionContext类,加一个SharedTempObjects字典,用来存会话级的临时对象 - 在创建临时对象的状态里,把对象存入字典,用唯一标识当键(比如结合会话GUID+对象类型,避免冲突)
- 后续状态从上下文字典里取出对象,用完可以直接移除,避免内存浪费
示例代码片段:
// 扩展后的会话上下文 public class SessionContext { public Guid SessionId { get; set; } // 会话专属的临时对象仓库 public Dictionary<string, object> SharedTempObjects { get; } = new(); // 替换静态计数的会话级计数 public int CreatedCount { get; set; } public int DisposedCount { get; set; } } // 在生成临时对象的初始状态里 public class InitialState : IState { public IState NextState(SessionContext context) { var tempObj = new YourTempObject(); // 用唯一键存入仓库 var key = $"{context.SessionId}_Temp_{typeof(YourTempObject).Name}"; context.SharedTempObjects.Add(key, tempObj); // 更新会话级创建计数 context.CreatedCount++; // 继续流程... return new FollowUpState(); } } // 在后续状态里使用临时对象 public class FollowUpState : IState { public IState NextState(SessionContext context) { var key = $"{context.SessionId}_Temp_{typeof(YourTempObject).Name}"; if (context.SharedTempObjects.TryGetValue(key, out var obj) && obj is YourTempObject tempObj) { // 这里用临时对象做业务逻辑 DoSomethingWithTempObj(tempObj); // 用完清理,同时更新销毁计数 context.SharedTempObjects.Remove(key); context.DisposedCount++; } // 继续流转... return null; } }
这个方案完美适配你现有的状态引擎架构,还解决了静态计数的问题——每个会话的计数独立,不会像全局静态变量那样跨会话混乱,线程安全也更容易保证。
2. 用Scoped服务托管临时对象(适合重构场景)
如果你有计划慢慢重构遗留代码,可以把需要共享的临时对象封装成Scoped服务:
- 把临时对象做成接口+实现类,比如
ITempSharedService和TempSharedService - 在DI容器里把它注册为Scoped生命周期(和会话生命周期绑定)
- 每个状态通过构造函数注入这个服务,同一会话内的所有状态都会拿到同一个实例
注意:要确保你的状态实例也是Scoped的,或者DI容器能正确识别会话范围,不然会拿到不同的实例。
3. 异步/跨场景用消息队列传递(复杂场景备选)
如果你的状态执行是异步的,甚至跨进程运行,那可以把临时对象序列化后存入消息队列,用会话GUID作为标识:
- 序列化临时对象(比如用Json.NET或System.Text.Json)
- 存队列时带上会话ID作为键
- 后续状态根据会话ID从队列里拉取对象,用完删除
不过这个方案复杂度高,适合分布式的复杂场景,一般小项目用不上。
关于静态计数的额外建议
你提到的CreatedCount和DisposedCount静态变量,因为是全局共享的,不仅会串会话数据,还容易有线程安全问题。建议改成:
- 在
SessionContext里加专属的计数属性,每个会话自己维护 - 或者用静态字典,键是会话GUID,值是该会话的计数对象(比如
Dictionary<Guid, SessionCounts>)
这样就能准确追踪每个会话的对象创建/销毁情况了。
内容的提问来源于stack exchange,提问作者Cody Barnes
相关产品推荐
相关产品推荐

