2017-05-16 60 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