c# - NDepend 和依赖注入(inject)——如何连接这些点?

标签 c# dependency-injection ndepend

请观察以下使用 MEF 作为依赖注入(inject)框架的简单程序:

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 的所有直接和间接调用者: enter image description here

但是,类 TestClient消耗 Test通过 ITest 实例使用依赖注入(inject)的接口(interface),因此寻找 ITest.DoSomething 的直接和间接调用者给我这个: enter image description here

所以,这给了我完整的画面 - Program.BackToProgram最终是从 Program.Main 调用的.

不幸的是,我不得不求助于手动代码检查来连接这些点。依赖注入(inject)似乎破坏了 NDepend 跨 DI 边界跟踪调用内容的能力。

虽然这可以用 DI 严重依赖反射这一事实来解释,而反射并不真正适合静态代码分析,但这带来了一个大问题,因为我们的代码大量使用 DI。

那么,这个问题有什么解决办法吗?有没有办法配置 NDepend 以识别由 MEF 实现的依赖注入(inject)?在一天结束时,当被问及 Program.BackToProgram 的所有直接和间接调用者时我希望看到 Program.Main在图表上没有人为干预。

也许还有其他工具可以做到这一点?

编辑 1

Patrick from NDepend team提供的答案很有趣,但还不够好。实际上,它返回了涉及的方法,但调用者图已断开连接: enter image description here

因此对于这个人为的例子,可以推断出缺失的连接。但这种奢侈在广泛使用 DI 的生产代码中是不存在的。我们最终会得到许多断开连接的子图。这对追踪调用者没有任何帮助。

最佳答案

可以套用this question的答案原样。

// 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 indirect method interface call

关于c# - NDepend 和依赖注入(inject)——如何连接这些点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38411635/

相关文章:

c# - OwinStartup时如何使用DI容器

javascript - 来自不同模块的 Angular 注入(inject)

c# - NDepend 中解决方案范围的命名空间依赖关系图

c# - 附件和 AttachmentData 之间的区别

c# - 使用 For 循环滑动对象 (C#)

javascript - 无法在angularjs中绑定(bind)范围变量

c# - 使用 NDepend 查找 System.Web.Caching.Cache 中放置特定对象类型的位置

c# - 仅保留使用过的类型并删除未使用的类型

c# - MVVM WPF 应用程序开发人员技能集

c# - 以编程方式自动化 Web 登录