NamedScopes Ninject绑定和异步(线程) [英] NamedScopes Ninject bindings and async (threading)
问题描述
我的项目是由服务和存储库结构(所有存储库共享数据库上下文)。在我的服务层中的一个,我有写使用存储库数据库中的异步方法。 web请求将完成和处置的上下文之前该方法可以得到使用它。我试图了解 NamedScopes 的在本回答。我似乎仍不能明白如何实现它。我会告诉我的项目是如何构成的,希望有人能帮助我在代码级别。
绑定
私有静态无效RegisterServices(的iKernel内核)
{
//的DbContext
kernel.Bind< EntityDatabaseContext>()。 ToMethod(上下文=>新建EntityDatabaseContext())。InRequestScope();
//工作
kernel.Bind&所述的单元; IUnitOfWork方式>()到<的UnitOfWork方式>()InRequestScope();
//库
kernel.Bind< IRepository<帐户>>()为<库<帐户>>()InRequestScope();
//服务
kernel.Bind&所述; IAuthenticationService>()至<的AuthenticationService方式>()InRequestScope();
}
的AuthenticationService使用构造函数注入
$ {}$ b
公开的AuthenticationService(;帐户> accountRepository的UnitOfWork的UnitOfWork,IRepository<) >
我的AuthenticationService内的方法
//这是一个后台进程
公共任务SomeMethodAsync(字符串文本)
{
//旋转它关到一个新的任务,
返回Task.Factory.StartNew(()=>的someMethod(文本));
}
的someMethod
利用的 accountRepository
。如果需要了信息请告诉我。请帮我穿线问题,如果NamedScopes是解决方案,我怎么实现它在我的情况?
基本上,正在执行的后台进程,它是使用正由ninject处置由于请求范围的上下文
解决方案 您应该知道,在运行的后台线程可以使你很多问题。 IIS可以决定回收随时应用程序池,将立即终止您的线程(或它不会在某些情况下执行的话)留下不一致的状态您的应用程序。
运行asyncronous操作的最简单和最容易出错京顺路是实现一个窗口服务,并委托这些异步操作的windows服务例如:使用MSMQ。
如果您还想去硬盘的方式,然后阅读 HostingEnvironment.RegisterObject
和 IRegisteredObject
来防止这些不一致的情况。
的 Ninject部分是很容易的。只是创造一些就业处理器类如 MyJobProcessor
采取一切需要的依赖来执行任务。它应该落实 INotifyWhenDisposed
。这样做最简单的方法是从 DisposeNotifyingObject
派生。
公开类MyJobProcessor:DisposeNotifyingObject,IRegisteredObject
{
公共无效执行(){...}
公共无效停止(BOOL立即){...}
}
注入该处理器的控制器,让任务启动它,处理它时,它已经完成它的工作。
Task.Factory.StartNew(()=>
{
试
{
processor.Execute();
}
终于
{
processor.Dispose);
}
});
指定这是其依赖的范围。
绑定< MyJobProcessor>()ToSelf()命名(MyJobProcessor)DefinesNamedScope(MyJobProcessorScope)。;
绑定&所述; IUnitOfWork方式>()到<的UnitOfWork方式>()WhenAnyAnchestorNamed(MyJobProcessor)InNamedScope(MyJobProcessorScope);
My project is structured by services and repositories (all repositories share the db context). In one of my service layers, I have an asynchronous method that writes to the database using a repository. The web request will finish and dispose of the context before this method can get to use it. I tried to understand NamedScopes as stated in this answer. I still can't seem to understand how to implement it. I'll show how my project is structured and hope someone can help me at the code level.
Bindings
private static void RegisterServices(IKernel kernel)
{
//dbcontext
kernel.Bind<EntityDatabaseContext>().ToMethod(context => new EntityDatabaseContext()).InRequestScope();
//unit of work
kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
//repositories
kernel.Bind<IRepository<Account>>().To<Repository<Account>>().InRequestScope();
//services
kernel.Bind<IAuthenticationService>().To<AuthenticationService>().InRequestScope();
}
AuthenticationService uses constructor injection
public AuthenticationService(UnitOfWork unitOfWork, IRepository<Account> accountRepository){}
A method inside my AuthenticationService
//this is a background process
public Task SomeMethodAsync(string text)
{
//spin it off into a new task
return Task.Factory.StartNew(() => SomeMethod(text));
}
SomeMethod
makes use of accountRepository
. Please tell me if anymore information is needed. Please help me with the threading issue, if NamedScopes is the solution, how do I implement it in my case?
Basically, a background process is being executed and it is using a context that is being disposed of by ninject due to the request scope.
解决方案 You should be aware that running background threads can cause you many problems. IIS can decide to recycle the app pool at any time which will terminate your thread immediately (or it doesn't execute in some cases at all) leaving your application in an inconsistent state.
The easiest and least error prone wayto run asyncronous operations is to implement a windows service and delegate those async operations to the windows service e.g. using MSMQ.
If you still want to go the hard way then read about HostingEnvironment.RegisterObject
and IRegisteredObject
to prevent these inconsistent situations.
The Ninject part is quite easy. Just create some job processor class e.g. MyJobProcessor
taking all required dependencies to execute the task. It should implement INotifyWhenDisposed
. The easiest way to do so is to derive from DisposeNotifyingObject
.
public class MyJobProcessor : DisposeNotifyingObject, IRegisteredObject
{
public void Execute() { ... }
public void Stop(bool immediate) { ... }
}
Inject this processor to the controller and let the Task start it and dispose it when it has finished its work.
Task.Factory.StartNew(() =>
{
try
{
processor.Execute();
}
finally
{
processor.Dispose);
}
});
Specify that it is the scope for its dependencies.
Bind<MyJobProcessor>().ToSelf().Named("MyJobProcessor").DefinesNamedScope("MyJobProcessorScope");
Bind<IUnitOfWork>().To<UnitOfWork>().WhenAnyAnchestorNamed("MyJobProcessor").InNamedScope("MyJobProcessorScope");
这篇关于NamedScopes Ninject绑定和异步(线程)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!