2017-05-16 62 views
1

我無法弄清楚爲什麼我得到一個循環依賴錯誤。我還得到了許多不同的激活路徑和類,這些激活路徑和類似乎是隨機的。Ninject與沒有依賴關係的綁定的循環依賴問題

這是一個已經工作了一年的系統中的一個新問題。它一直處於積極的發展階段,因此它不斷變化,並試圖回滾變化,以確定在這個時刻出現問題的確切位置有點過於繁瑣。

似乎這與多線程和競爭條件有關。當我添加更多線程運行時,錯誤更頻繁出現。

當Ninject發出的一條激活路徑/依賴關係引起了我的注意時,我一直在努力解決這個問題。 我列出的其中一個依賴項本身沒有任何依賴關係。

Ninject.ActivationException: Error activating IMetaValueProvider using binding from IMetaValueProvider to ExecutionOutputMetaValueProvider 
A cyclical dependency was detected between the constructors of two services. 

Activation path: 
    6) Injection of dependency IMetaValueProvider into parameter valueProviders of constructor of type MetaValueResolverFactory 
    5) Injection of dependency IMetaValueResolverFactory into parameter valueResolverFactory of constructor of type MessageExecutionContextFactory 
    4) Injection of dependency IMessageExecutionContextFactory into parameter executionContextFactory of constructor of type MessageProcessor 
    3) Injection of dependency IMessageProcessor into parameter messageProcessor of constructor of type MessageProcessingManager 
    2) Injection of dependency IMessageProcessingManager into parameter messageProcessingManager of constructor of type QueuePollerFactory 
    1) Request for QueuePollerFactory 

在上述例子中,ExecutionOutputMetaValueProvider完全沒有相關性。

下面是源ExecutionOutputMetaValueProvider

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace DealerVision.Messaging 
{ 
    public class ExecutionOutputMetaValueProvider : IMetaValueProvider 
    { 
     public string MetaKeyPrefix 
     { 
      get 
      { 
       return "Output"; 
      } 
     } 

     public object GetMetaValue(IMessageExecutionContext context, string key) 
     { 
      if(context.ExecutableMessage.Result == null) 
      { 
       throw new Exception($"{nameof(ExecutionOutputMetaValueProvider)} cannot get key \"{key}\" because the {nameof(ExecutableMessageBase)} does not have a result."); 
      } 

      if (context.ExecutableMessage.Result.ExecutionOutput.ContainsKey(key)) 
      { 
       return context.ExecutableMessage.Result.ExecutionOutput[key]; 
      } 

      return null; 
     } 

     public IEnumerable<string> GetPersistantKeys(IMessageExecutionContext executionContext) 
     { 
      if (executionContext.ExecutableMessage.Result == null) 
       return Enumerable.Empty<string>(); 

      List<string> keys = new List<string>(); 

      foreach (var kvp in executionContext.ExecutableMessage.Result.ExecutionOutput) 
      { 
       keys.Add($"{this.MetaKeyPrefix}.{kvp.Key}"); 
      } 

      return keys; 
     } 
    } 
} 

兩個問題:

  1. 我怎樣才能知道確切的週期性2和依賴關係是什麼? Ninject沒有列出只涉及其中一個循環的BOTH依賴關係。
  2. 如果該依賴項本身沒有任何依賴關係,那麼如何將這個依賴項稱爲循環的一部分。怎麼可能有一個循環?

我顯然錯過了一些東西。任何幫助,將不勝感激。

+1

請張貼最小可驗證示例示出了問題。 – Steven

+0

這是使用asp.net,asp.net MVC嗎? WCF? – BatteryBackupUnit

+0

@BatteryBackupUnit,不,它是一個控制檯應用程序。 –

回答

1

實例需要「自下而上」或「先依賴」創建。這意味着,ExecutionOutputMetaValueProviderMessageExecutionContextFactory之前創建,並且在... QueuePollerFactory之前再次創建。

現在,ninject停止在ExecutionOutputMetaValueProvider,因爲這會導致在鏈中進一步創建類型。在這一點上,它沒有確切地說明那將是。

既然你說ExecutionOutputMetaValueProvider沒有任何依賴關係: 。

  • 檢查你是否是錯誤的:
    • 有不止一個構造函數?因爲如果有一個構造函數的ninject具有綁定的參數,它將使用這一個,而不是沒有參數的那個
    • 是否有屬性或方法注入?另請參閱here
    • 是否存在具有相同名稱的第二種類型 - 綁定實際上是針對其他類型的,而不是您期望的那種? (同時檢查Rebind和條件綁定)。
  • 支票的OnActivation使用 - 這可導致耦合到的類型
  • 用法DependencyCreation延伸instanciation激活還可以導致非顯而易見的激活
+0

我已將源代碼包含在「ExecutionOutputMetaValueProvider」中。你可以看到,沒有依賴關係。這種綁定如何可能導致週期性依賴性問題? –

+0

@RyanGriffith就像我在帖子中說的那樣,OnActivation或DependencyCreation可以掩蓋這種「依賴」 - 因爲它們沒有被注入。 – BatteryBackupUnit