2017-07-31 67 views
0

我想在我的应用程序中使用Ninject自定义作用域,以便将DbContext的单个激活作用域包含到我的核心域处理程序中。然而,我遇到了麻烦,因为CommandScope对象实现了Ninject的一部分INotifyWhenDisposed接口,并且我不想在我的域中依赖Ninject。为确定性处理注入Ninject作用域对象

我已经尝试了许多其他方式来获得依赖到代码中,没有成功,包括使用Ninject工厂来公开一个IScopeFactory和一个Func依赖。在后一种情况下,问题是(我认为)Ninject不会连接INotifyWhenDisposed.Dispose事件,因为绑定目标是Func而不是IDisposable本身。

无论如何,这是我想要实现的代码。

的IoC

Kernel 
    .Bind<MyDbContext>() 
    .ToSelf() 
    .InScope(x => CommandScope.Current) 
    .OnDeactivation(x => x.SaveChanges()); 

CommandScope

public class CommandScope : INotifyWhenDisposed 
{ 
    public event Dispose; 

    public bool IsDisposed { get; private set; } 

    public static CommandScope Current { get; private set; } 

    public static CommandScope Create() 
    { 
     CommandScope result = new CommandScope(); 
     Current = result; 
     return result; 
    } 

    public void Dispose() 
    { 
     IsDisposed = true; 
     Current = null; 
     Dispose?.Invoke(this, EventArgs.Empty); 
    } 
} 

里面我的域名......

public class Pipeline<TRequest, TResponse> 
{ 
    readonly IRequestHandler<TRequest, TResponse> innerHandler; 

    public Pipeline(IRequestHandler<TRequest, TResponse> handler) 
    { 
     innerHandler = handler; 
    } 

    public TResponse Handle(TRequest request) 
    { 
     using(CommandScope.Create()) 
     { 
      handler.Handle(request); 
     } 
    } 
} 
+0

但是,您的Pipeline类是一些基础代码,因此您可以将它提取到与包含域逻辑的项目不同的项目。或者你还有其他问题? –

回答

1

你可以使用Decorator模式(需要一个接口),只有具备装饰器INotifyWhenDisposed接口 - 然后将装饰器放在组合根部 - 在那里反正你需要一个ninject参考。

或者,你可以使用一个Func工厂,创建一个IDisposable,它实现了INotifyWhenDisposed(然而消费库不需要知道这个)。在访问组合根目录中的实例时,仍然可以将其转换为INotifyWhenDisposed(实际上可能不需要)。例如:

.InScope(x => (INotifyWhenDisposed)CommandScope.Current) 

在设计上留言:我会highyl建议CommandScope分成两类:一工厂和实际范围。 另外,从长远来看,通过确保新的范围(由Create创建)不会替代尚未处理的旧范围,您可能会节省很多头痛。否则,你可能会错过你介绍的泄漏。

0

清除从Ninject的ICache范围对象将迫使Ninject关闭和处置的范围控制的所有实例:

var activationCache = Kernel.Get<Ninject.Activation.Caching.ICache>(); 
activationCache.Clear(CommandScope.Current); 

你也可以考虑NamedScope extension有你的单例模式CommandScope更好的选择。