我有几个循环,每个循环都通过ConcurrentQueue<T>
. 这些流程调用一些业务服务实现,它们使用存储库进行数据库交互。服务实现都是通过 StructureMap 连接起来的。
存储库实现具有一些需要仔细管理的特征:
- 正在使用的数据库技术是Redis。
- 该实现使用 ServiceStack.net 的 Redis 客户端(通过 a
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 );
}
}
我认为这解释了情况和目标。我的问题如下:
- 如上所述,我可以使用 StructureMap 在单个进程的上下文中使用不同的范围。
- 我不想在我的域/服务层中包含对 StructureMap 的直接依赖。因此,如果我能够在此阶段使用不同的范围,是否有一种简单的方法可以做到这一点,而无需从流程本身直接调用 StructureMap?
- 我可以通过 DSL 配置指示 StructureMap 在流程结束时处理存储库,还是需要在我的代码中明确执行此操作?