2017-07-31 39 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更好的選擇。