在我服务层我已经注入了UnitOfWork
和2个仓库在构造函数中。 工作和存储库的单位有一个实例DbContext
我想他们两个人之间的共享。 我如何能做到这一点与Ninject? 其范围应被考虑?
我不是一个Web应用程序 ,所以我不能用InRequestScope
。
我试图做同样的事情......但是和我使用DI,我需要我的UOW是Dispose
d和这样的创造。
using (IUnitOfWork uow = new UnitOfWorkFactory.Create())
{
_testARepository.Insert(a);
_testBRepository.Insert(b);
uow.SaveChanges();
}
编辑:我只是想知道我知道......看后https://github.com/ninject/ninject.extensions.namedscope/wiki/InNamedScope我虽然哪些实际使用Ninject我目前的控制台应用程序架构。
比方说:
类是一服务层类
B类是工作的一个单元,其考虑到参数的接口(IContextFactory)
C类是一个储存库,其考虑到参数的接口(IContextFactory)
这里的想法是要能够做2个或多个存储库和使用工作的单位以应用更改上下文操作。
d类是一个上下文工厂(实体框架),它提供一个实例(保持在容器中),其被B类等℃之间共享的上下文的(..和将成为其他存储库藏汉)。
上下文工厂保持比如在他的容器,所以我不想因为上下文需要在服务operaiton年底被安置..它是InNamedScope实际上的主要目的重用这种情况下所有的名字吗?
解决办法是,但我不知道在我的全部做的是正确的服务实例会被transcient这意味着他们却从未配置? :
Bind<IScsContextFactory>()
.To<ScsContextFactory>()
.InNamedScope("ServiceScope")
.WithConstructorArgument(
"connectionString",
ConfigurationUtility.GetConnectionString());
Bind<IUnitOfWork>().To<ScsUnitOfWork>();
Bind<IAccountRepository>().To<AccountRepository>();
Bind<IBlockedIpRepository>().To<BlockedIpRepository>();
Bind<IAccountService>().To<AccountService>().DefinesNamedScope("ServiceScope");
Bind<IBlockedIpService>().To<BlockedIpService>().DefinesNamedScope("ServiceScope");
更新:这种方法适用反对的NuGet电流,但依靠在异常InCallscope
已被固定在当前不稳定的NuGet包实现。 我将在几天内调整这个答案,以反映最好的办法经过一番思索。 NB的结构材料的高层次的方式将保持几乎相同,只是确切的细节Bind<DbContext>()
作用域会工作。 (提示: CreateNamedScope
不稳定会工作或一个可以设置命令处理程序DefinesNamedScope
。我之所以不只是做到这一点的是,我想有一些组成/有打得很好InRequestScope
)
我强烈建议你阅读的Ninject.Extensions.NamedScope
集成测试(严重的是,找到他们,阅读和重新阅读)
该DbContext
是一个单位工作,所以没有进一步的包装是必要的。
当你希望能够有多个“要求”在飞行中,并希望有它们之间共享一个单独的工作单位,您需要:
Bind<DbContext>()
.ToMethod( ctx =>
new DbContext(
connectionStringName: ConfigurationUtility.GetConnectionString() ))
.InCallScope();
所述InCallScope()
表示:
- 对于一个由给定对象图
kernel.Get()
调用 (因此,在呼叫范围),每个人都需要一个DbContext
会得到相同的实例。 - 在
IDisposable
。 Dispose()
时,将被称为Kernel.Release()
发生根对象(或Kernel.Components.Get<ICache>().Clear()
发生根如果它不是.InCallScope()
不应该有任何理由使用InNamedScope()
和DefinesNamedScope()
; 你没有你想从默认池/育儿/分组排除长期对象。
如果你做到上面,你应该能够:
var command = kernel.Get<ICommand>();
try {
command.Execute();
} finally {
kernel.Components.Get<ICache>().Clear( command ); // Dispose of DbContext happens here
}
命令执行是这样的:
class Command : ICommand {
readonly IAccountRepository _ar;
readonly IBlockedIpRepository _br;
readonly DbContext _ctx;
public Command(IAccountRepository ar, IBlockedIpRepository br, DbContext ctx){
_ar = ar;
_br = br;
_ctx = ctx;
}
void ICommand.Execute(){
_ar.Insert(a);
_br.Insert(b);
_ctx.saveChanges();
}
}
注意,一般来说,我避免在这种方式工作的隐式单位,而是表面它的创建和Disposal
。 这使得一个命令是这样的:
class Command : ICommand {
readonly IAccountService _as;
readonly IBlockedIpService _bs;
readonly Func<DbContext> _createContext;
public Command(IAccountService @as, IBlockedIpServices bs, Func<DbContext> createContext){
_as = @as;
_bs = bs;
_createContext = createContext;
}
void ICommand.Execute(){
using(var ctx = _createContext()) {
_ar.InsertA(ctx);
_br.InsertB(ctx);
ctx.saveChanges();
}
}
这涉及到的无用法.InCallScope()
的Bind<DbContext>()
但是需要的存在Ninject.Extensions.Factory
的FactoryModule
合成Func<DbContext>
从一个简单的Bind<DbContext>()
正如在讨论对方的回答 , InCallScope
是不是一个好的方法来解决这个问题。
现在我倾倒一些代码,针对最新的NuGet不稳定工作/包括抢鲜/ Instal-Package -Pre
的版本Ninject.Web.Common
没有一个明确的解释。 我会翻译这在一篇文章Ninject.Extensions.NamedScope
在某个阶段维基已经开始写这种技术的演练中Ninject.Extensions.NamedScope
维基CreateNamedScope / GetScope文章 。
可能还有一些位将成为在某一阶段上拉请求(S)太(帽尖到@Remo Gloor谁给我提供了大纲代码)。 在相关的测试和学习测试是在这个要点现在 ),等待以适当的格式发布TBD包装。
这位经理总结为您加载模块下方进内核,并使用.InRequestScope()
上的一切你想创建/ Dispose
每处理程序调用d,然后经由饲料请求IHandlerComposer.ComposeCallDispose
。
如果您使用以下模块:
public class Module : NinjectModule
{
public override void Load()
{
Bind<IHandlerComposer>().To<NinjectRequestScopedHandlerComposer>();
// Wire it up so InRequestScope will work for Handler scopes
Bind<INinjectRequestHandlerScopeFactory>().To<NinjectRequestHandlerScopeFactory>();
NinjectRequestHandlerScopeFactory.NinjectHttpApplicationPlugin.RegisterIn( Kernel );
}
}
其中导线在工厂[1]和NinjectHttpApplicationPlugin
暴露:
public interface INinjectRequestHandlerScopeFactory
{
NamedScope CreateRequestHandlerScope();
}
然后你可以使用这个作曲家运行请求InRequestScope()
public interface IHandlerComposer
{
void ComposeCallDispose( Type type, Action<object> callback );
}
实现为:
class NinjectRequestScopedHandlerComposer : IHandlerComposer
{
readonly INinjectRequestHandlerScopeFactory _requestHandlerScopeFactory;
public NinjectRequestScopedHandlerComposer( INinjectRequestHandlerScopeFactory requestHandlerScopeFactory )
{
_requestHandlerScopeFactory = requestHandlerScopeFactory;
}
void IHandlerComposer.ComposeCallDispose( Type handlerType, Action<object> callback )
{
using ( var resolutionRoot = _requestHandlerScopeFactory.CreateRequestHandlerScope() )
foreach ( object handler in resolutionRoot.GetAll( handlerType ) )
callback( handler );
}
}
该Ninject基础的东西:
class NinjectRequestHandlerScopeFactory : INinjectRequestHandlerScopeFactory
{
internal const string ScopeName = "Handler";
readonly IKernel _kernel;
public NinjectRequestHandlerScopeFactory( IKernel kernel )
{
_kernel = kernel;
}
NamedScope INinjectRequestHandlerScopeFactory.CreateRequestHandlerScope()
{
return _kernel.CreateNamedScope( ScopeName );
}
/// <summary>
/// When plugged in as a Ninject Kernel Component via <c>RegisterIn(IKernel)</c>, makes the Named Scope generated during IHandlerFactory.RunAndDispose available for use via the Ninject.Web.Common's <c>.InRequestScope()</c> Binding extension.
/// </summary>
public class NinjectHttpApplicationPlugin : NinjectComponent, INinjectHttpApplicationPlugin
{
readonly IKernel kernel;
public static void RegisterIn( IKernel kernel )
{
kernel.Components.Add<INinjectHttpApplicationPlugin, NinjectHttpApplicationPlugin>();
}
public NinjectHttpApplicationPlugin( IKernel kernel )
{
this.kernel = kernel;
}
object INinjectHttpApplicationPlugin.GetRequestScope( IContext context )
{
// TODO PR for TrgGetScope
try
{
return NamedScopeExtensionMethods.GetScope( context, ScopeName );
}
catch ( UnknownScopeException )
{
return null;
}
}
void INinjectHttpApplicationPlugin.Start()
{
}
void INinjectHttpApplicationPlugin.Stop()
{
}
}
}