NDepend и внедрение зависимостей - как соединить точки?

Обратите внимание на следующую тривиальную программу, использующую MEF в качестве фреймворка для внедрения зависимостей:

using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;

namespace ConsoleApplication2
{
    [InheritedExport]
    public interface ITest
    {
        void DoSomething();
    }

    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class Test : ITest
    {
        #region Implementation of ITest

        public void DoSomething()
        {
            Program.BackToProgram();
        }

        #endregion
    }

    [Export]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class TestClient
    {
        private readonly ITest m_test;

        [ImportingConstructor]
        public TestClient(ITest test)
        {
            m_test = test;
        }

        public void DoSomethingFromTestClient()
        {
            m_test.DoSomething();
        }
    }

    class Program
    {
        private static CompositionContainer m_container;

        static void Main()
        {
            m_container = new CompositionContainer(new TypeCatalog(typeof(Test), typeof(TestClient)), true);
            var testClient = m_container.GetExportedValue<TestClient>();
            testClient.DoSomethingFromTestClient();
        }

        public static void BackToProgram()
        {
        }
    }
}

Теперь давайте проанализируем это с помощью NDepend 6.3. Предположим, я хочу знать всех прямых и косвенных абонентов Program.BackToProgram:  введите описание изображения здесь

Однако класс TestClient использует экземпляр Test через интерфейс ITest с помощью внедрения зависимостей, поэтому поиск прямых и косвенных вызывающих ITest.DoSomething дает мне следующее:  введите описание изображения здесь

Итак, это дает мне полную картину - Program.BackToProgram в конечном итоге вызывается из Program.Main.

К сожалению, мне пришлось прибегнуть к проверке кода вручную, чтобы соединить точки. Внедрение зависимостей, похоже, нарушает способность NDepend отслеживать то, что вызывает, через границы DI.

Хотя это можно объяснить тем фактом, что DI в значительной степени полагается на отражение и что отражение на самом деле не поддается статическому анализу кода, тем не менее это создает большую проблему, потому что наш код довольно часто использует DI.

Итак, есть ли решение этой проблемы? Есть ли способ настроить NDepend для распознавания внедрения зависимостей, реализованного в MEF? В конце концов, когда меня спросят обо всех прямых и косвенных абонентах Program.BackToProgram, я хочу видеть Program.Main на графике без вмешательства человека.

Может, есть другой инструмент, который это делает?

ИЗМЕНИТЬ 1

Ответ, предоставленный Патриком из команды NDepend, интересен, но недостаточно хорош. Действительно, он возвращает задействованные методы, но граф вызывающих абонентов отключен:  введите описание изображения здесь

Итак, для этого надуманного примера можно вывести отсутствующее соединение. Но эта роскошь недоступна в производственном коде, который широко использует DI. У нас будет много несвязных подграфов. Отслеживание звонков не поможет.


person mark    schedule 16.07.2016    source источник
comment
Сторонники закрытия - какие-либо причины? Если у вас есть предложение по другому форуму, где разместить мой вопрос - говорите свободно.   -  person mark    schedule 18.07.2016


Ответы (1)


Вы можете применить ответ на этот вопрос как есть.

// Retrieve the target method by name
let methodTarget = Methods.WithFullName("ConsoleApplication2.Program.BackToProgram()").Single()

// Build a ICodeMetric<IMethod,ushort> representing the depth of indirect
// call of the target method.
let indirectCallDepth = 
   methodTarget.ToEnumerable()
   .FillIterative(
       methods => methods.SelectMany(
          m => m.MethodsCallingMe.Union(m.OverriddensBase)))

from m in indirectCallDepth.DefinitionDomain
select new { m, callDepth = indirectCallDepth[m]  }

и вуаля :)

Вызов интерфейса косвенного метода NDepend

person Patrick from NDepend team    schedule 18.07.2016
comment
См. ИЗМЕНИТЬ 1. - person mark; 18.07.2016
comment
Действительно, график отключен, потому что график показывает только статические зависимости, в то время как вы хотите, чтобы он отображал динамические зависимости IoC. Пока только запрос кода достаточно умен, чтобы угадать динамические зависимости IoC. - person Patrick from NDepend team; 18.07.2016
comment
Обратите внимание, что существует потребность в улучшенной поддержке IoC, проголосуйте за эту функцию здесь ndepend.uservoice.com/forums/226344-ndepend-user-voice/ - person Patrick from NDepend team; 18.07.2016
comment
Проголосовал. Это действительно назрело. - person mark; 18.07.2016
comment
Спасибо, Марк, мы делаем все возможное, чтобы расставить приоритеты по функциям и убедиться, что поддержка IoC занимает одно из первых мест в нашем списке TODO. - person Patrick from NDepend team; 19.07.2016
comment
Спасибо, надеюсь скоро увидим. - person mark; 19.07.2016