如何将基于“使用”的 GC 生命周期打开为基于“创建-处置”的生命周期?

Posted

技术标签:

【中文标题】如何将基于“使用”的 GC 生命周期打开为基于“创建-处置”的生命周期?【英文标题】:How do I break a 'using' based GC lifetime open into a 'create-dispose' based lifetime? 【发布时间】:2012-04-17 21:58:54 【问题描述】:

我专门指的是Impersonating user with Entity Framework 的公认答案,其中包含以下代码:

using (((WindowsIdentity)HttpContext.Current.User.Identity).Impersonate())
using (var dbContext = new MyEntityFrameworkContainer())

    ...

我宁愿只在我的存储库中的一个地方实例化dbContext,它实现IDisposable,然后在处置实体时处置上下文。我不确定上面的两个using 作用域是如何相互影响的,那么如何在避免使用块的同时实现这段代码在模拟方面的作用?

添加: 正如下面的答案所建议的那样,我可以简单地使用局部变量并“手动”确保资源被释放,但我在这里担心的是内部using 中的实例化是否会受到外部using 的影响。如果这只是一生的问题,并且外部 using 没有建立任何上下文或影响内部的任何内容,那么以下答案已经回答了我的问题。

【问题讨论】:

旁注:延长在模拟用户身份(数据库连接、文件、进程)下创建的对象的生命周期可能是严重的安全问题。考虑在完成模拟后使其难以继续使用此类对象。制作类似 Repository.ForImpersonatedUser(identity) 的东西可能是一种选择。 @AlexeiLevenkov,我不明白你建议我用 Repository.ForImpersonatedUser(identity) 做什么 您的存储库可能包含在模拟期间创建的对象(即在特定用户帐户下连接到数据库)。如果此对象与可能以或可能不以同一用户身份运行的其他代码共享,则您有问题。因此,您可以拥有为特定用户创建的对象的存储库,并在完成模拟后立即销毁存储库。根据数据的敏感性,您可能需要编写额外的代码来强制对象在模拟结束后不提供任何信息。 @AlexeiLevenkov,所以ForImpersonatedUser 是一个因子方法,它返回一个模拟传递的身份的仓库? 是的。如果您碰巧遇到问题,请选择任何方法来实现它 - 我只是想提出简短的自我描述名称...... 【参考方案1】:

您可以将它们声明为 2 个私有字段并在构造函数中实例化它们。

然后实现 Dispose() 并以相反的顺序处理它们。

当然,调用代码(业务层)应该将using() 模式应用于存储库实例。

补充:

嵌套使用不应该很重要。 Impersonate() 是影响当前线程的状态更改。 using 隐含的 Dispose() 将调用 Undo()。

【讨论】:

外部using 不返回任何值供我存储。我想嵌套使用在这里做了一些我不想破坏的巫术。 你可以简单的看成using(myTemp = ...)【参考方案2】:
var id = ((WindowsIdentity)HttpContext.Current.User.Identity).Impersonate();
//store id
//do whatever you want, for example store this variable in a field
id.Dispose(); //remove impersonation

【讨论】:

var 表示本地变量。这只会删除异常安全性,不会增加任何内容。 他可以将这个变量的内容存储在任何地方,包括在一个字段中。我添加了这种可能性作为评论。 @usr,我如何处理存储的id?我假设使用我所指的答案中的代码,在外部 using 内部创建的 dbContext 以某种方式隐式使用了该值。 可能我以某种方式误解了这个问题并解决了错误的问题。不确定。

以上是关于如何将基于“使用”的 GC 生命周期打开为基于“创建-处置”的生命周期?的主要内容,如果未能解决你的问题,请参考以下文章

Java WebSocket生命周期

对象生命周期中至少被GC一次后存活

在API中如何做数据隐私保护

☆Django☆---表的设计 生命周期 分组 解析 路由层 视图层

Rust语言:基于变量生命周期进行编译时SQL注入防止

Unit 5