Ninject循环依赖问题与没有依赖关系的绑定

时间:2017-05-16 20:46:48

标签: c# .net 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没有列出循环中涉及的两个依赖项,只列出其中一个。
  2. 如果该依赖项本身没有依赖项,那么如何将被调用的一个依赖项视为循环的一部分。怎么可能有一个循环?
  3. 我显然错过了一些东西。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

需要创建实例&#34;自下而上&#34;或者&#34;依赖首先&#34;。这意味着ExecutionOutputMetaValueProviderMessageExecutionContextFactory之前创建,并且再次在... QueuePollerFactory之前创建。

现在,ninject确实在ExecutionOutputMetaValueProvider处停止,因为这会导致在链中进一步创建类型。在这一点上,并没有明确说明那是什么。

因为你说ExecutionOutputMetaValueProvider没有任何依赖关系:

  • 检查你是否错了:
    • 是否有多个构造函数?因为如果有一个带有ninject具有绑定参数的构造函数,它将使用这个,而不是没有参数的那个
    • 是否有财产或方法注入?另请参阅here
    • 是否存在具有相同名称的第二种类型 - 并且绑定实际上是针对另一种类型,而不是您期望的那种? (还要检查Rebind和条件绑定)。
  • 检查OnActivation的使用情况 - 这可能导致激活与类型的实例相结合
  • DependencyCreation扩展名的使用也可能导致不明显的激活