gpt4 book ai didi

c# - StructureMap:特定上下文中的自定义生命周期范围

转载 作者:太空宇宙 更新时间:2023-11-03 14:04:58 24 4
gpt4 key购买 nike

我有几个循环,每个循环都通过 ConcurrentQueue<T> 生成异步进程。 .这些流程调用一些使用存储库进行数据库交互的业务服务实现。服务实现全部通过 StructureMap 连接起来。

存储库实现具有一些需要仔细管理的特征:

  • 正在使用的数据库技术是Redis .
  • 实现使用 ServiceStack.net 的 Redis 客户端(通过 PooledRedisClientManager )。
  • 有几种方法利用了(我相信)不能由同一个 RedisClient 同时创建的事务。因此,不可能在多个异步进程上共享单个存储库实现,因为它会尝试同时创建多个事务。
  • 为了释放内存和数据库连接,需要显式处理这些对象 - 因此我在存储库类上实现了 IDisposable。
  • 没有理由不能在单个异步进程的范围内共享存储库实例,因为不会有并发请求/事务。

考虑到上述情况,我想将单个存储库实例的范围限定为每个异步进程的生命周期。

要记住的一件事是,在异步进程范围内使用的服务也被系统的其他部分使用,这些部分具有不同的生命周期特征(例如,在一个网站中,存储库的范围是生命周期页面请求)。

我将尝试用一些代码(从我的代码中简化)来说明:

管理队列的程序(以及连接执行 IAsyncResult 调用的事件处理程序):

public class Program
{
private readonly ConcurrentQueue<QueueItem> queue = new ConcurrentQueue<QueueItem>();
private readonly IItemManager itemManager; // implemented via constructor DI.

public void ProcessQueueItems()
{
while ( queue.Count > 0 || shouldContinueEnqueuing )
{
QueueItem item;
if ( queue.TryDequeue( out item ) )
{
// Begin async process here - only one repository should be used within the scope of this invocation
// (i.e. withing the scope of the itemManager.ProcessItem( item ) method call.
new ItemProcessor( itemMananger.ProcessItem ).BeginInvoke( e.Item, ItemCallback, null );
}

Thread.Sleep( 1 );
}

}

private static void ItemCallback( IAsyncResult result )
{
var asyncResult = ( AsyncResult ) result;
var caller = ( ItemProcessor ) asyncResult.AsyncDelegate;

var outcome = caller.EndInvoke( result );

// Do something with outcome...
}

private delegate ItemResult ItemProcessor( QueueItem item );
}

异步结果调用的实现。我想管理 ProcessItem( ... ) 范围内的范围方法:

public class ItemManager : IItemManager
{
private readonly IServiceA serviceA; // implemented via constructor DI.
private readonly IServiceB serviceB; // implemented via constructor DI.

public ItemResult ProcessItem( QueueItem item )
{
// Both serviceA and serviceB use the repository which is injected via StructureMap. They should share
// the instance and at the end of the process it should be disposed (manually, if needs be).
var something = serviceA.DoSomething( item );

return serviceB.GetResult( something );
}
}

我认为这可以解释情况和目标。我的问题如下:

  1. 我能否使用 StructureMap 在单个进程的上下文中使用不同的范围,如上所述。
  2. 我不想在我的域/服务层中包含对 StructureMap 的直接依赖。那么,如果我在这个阶段能够使用不同的范围,是否有一种简单的方法可以做到这一点而无需直接从流程本身内部调用 StructureMap?
  3. 我能否通过 DSL 配置指示 StructureMap 在流程结束时处理存储库,或者我是否需要在我的代码中明确执行此操作?

最佳答案

你可以使用 nested container对于这种情况。

The nested container will track all of the transient objects that it creates. When the nested container itself is disposed, it will call Dispose() on any of the transient objects that it created.

var nestedContainer = container.GetNestedContainer();
var processor = nestedContainer.GetInstance<IItemProcessor>();

确保每个对象都使用相同存储库的其他方法是使用 With() 方法

// Get the IRepository which should be shared   
// This object is registered using simple
// For<ISession>.Use<Session> registration so not scoped
// http context or anything like that
var session = container.GetInstance<ISession>();

// Create instance of IProcessor using the specific instance
// of ISession. If multiple classes in the object grap use ISession
// they will get the same instance. Note that you can use multiple
// With() statements
var itemProcessor = container.With(session).GetInstance<IItemProcessor>();

关于c# - StructureMap:特定上下文中的自定义生命周期范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9584099/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com