【问题标题】:Finding code only used in special classes via NDepend通过 NDepend 查找仅在特殊类中使用的代码
【发布时间】:2012-11-02 14:43:31
【问题描述】:

我正在尝试使用 NDepend 删除我们代码库中的死代码。由于我们使用依赖注入,我想找到仅在从注册表库派生的类中使用的接口(和实现):

public class PresenterRegistry : Registry
{
    public PresenterRegistry()
    {
        For<IExamplePresenter>().Use<ExamplePresenter>();
    }
}

有什么办法吗?

谢谢!

【问题讨论】:

    标签: c# dependency-injection ndepend static-code-analysis


    【解决方案1】:

    经过一点尝试,我创建了一个按我需要的方式工作的查询:

    // <Name>Interfaces registered but potentially not used</Name>
    warnif count > 0 
    from t in JustMyCode.Types
    from i in JustMyCode.Types
    where t.DeriveFrom("StructureMap.Configuration.DSL.Registry")
       && i.IsInterface
       && t.IsUsing(i)
       && i.NbTypesUsingMe < 3 // one using for implementation, one in registry
    select i
    

    没有我预期的那么多代码 :-) 这个查询没有涵盖任何可能性,但它是一个好的开始。

    不过:Patrick,感谢您的帮助!


    不客气,Rico :) 顺便说一句,这个代码规则可以这样重写,以在 O(N) 而不是 O(N^2) 中运行( N 是 JustMyCode.Types 的数量)。这种优化是通过神奇的UsedByAny() 方法实现的。此规则还提供了更详细的结果。

    warnif count > 0 
    let registryDerived = JustMyCode.Types.Where(t => t.DeriveFrom("StructureMap.Configuration.DSL.Registry"))
    from i in JustMyCode.Types.UsedByAny(registryDerived)
    where i.IsInterface &&
          i.NbTypesUsingMe < 3 // one using for implementation, one in registry
    select new { i, 
                 registryDerivedUser = i.TypesUsingMe.Intersect(registryDerived),
                 i.TypesUsingMe }
    

    【讨论】:

      【解决方案2】:

      我不确定你的要求是什么。

      我想查找仅在派生自注册表库的类中使用的接口(和实现): 以下查询匹配从 Microsoft.Win32.Registry 派生的任何类型使用的应用程序接口和类:

      let registryDerived = Application.Types.Where(t => t.DeriveFrom("Microsoft.Win32.Registry"))
      from t in Application.Types.UsedByAny(registryDerived)
      select t
      

      ..通过下一个查询,您还可以获得与上一个查询匹配的接口的派生类型和实现:

      let registryDerived = Application.Types.Where(t => t.DeriveFrom("Microsoft.Win32.Registry"))
      from t in Application.Types.UsedByAny(registryDerived)
      let tDerived = t.DerivedTypes
      let tImpl = t.TypesThatImplementMe
      select new { t, tDerived, tImpl }
      

      ...或全部列出:

      let registryDerived = Application.Types.Where(t => t.DeriveFrom("Microsoft.Win32.Registry"))
      
      let tUsed = Application.Types.UsedByAny(registryDerived)
      let tDerived = tUsed.SelectMany(t => t.DerivedTypes)
      let tImpl = tUsed.SelectMany(t => t.TypesThatImplementMe)
      
      from t in tUsed.Union(tDerived).Union(tImpl)
      select t
      

      顺便说一句,Microsoft.Win32.Registry 是密封的,所以你说的不是类。但是你可以用你自己的类名替换它,前缀为命名空间。

      【讨论】:

      • 感谢您的回复!这不完全是我需要的:上面的示例为我提供了从我的注册表基本类型中使用的所有类型。但我需要知道注册表中only 使用的代码。你明白我的意思吗?提前致谢!
      • 仅在注册表中使用的代码是指.NET Fx类Microsoft.Win32.Registry和类中使用的代码吗Microsoft.Win32.Registry 使用的以及 ... 使用的类等等?或者您的意思是在注册表中访问的密钥?
      • 你好。不,我的意思是在 StructureMap.Configuration.DSL.Registry 类型中使用的代码。它用于配置我们的依赖注入容器。我的目标是找到仅在这些类中使用而在我们的代码库中没有其他地方使用的类型和接口。这意味着找到的类型只是注册但没有使用,所以它是可以正确删除的死代码。由于我们使用依赖注入和 TDD,因此很难找到死代码,因为代码至少被测试类和 DI 容器的注册使用,如上所述。谢谢!
      • 好吧,你从来没有提到过 StructureMap,因此我对注册表的含义感到困惑?!到目前为止,NDepend 不读取 StructureMap 或其他 DI Fx 文件。但是您仍然可以编写一个程序,1) 读取 DI Fx 文件 2) 使用 NDepend.API 解析在 DI Fx 文件中找到的类型,然后查看它们的用法。 ndepend.com/API/webframe.html
      • 好的,很抱歉缺少信息。但我仍然认为这无关紧要。我们用于配置从注册表基类继承的 StructureMap 类(不是 xml,请参阅我最初帖子中的示例)。也许将我的问题与具体用例(StructureMap)联系起来有点令人困惑。同样的问题可能是:我需要在 MyOwnBaseClass 的任何派生中找到 only 使用的接口(如上面示例中的 IExamplePresenter)。你现在明白我的意思了吗?再次对任何误解表示歉意。
      猜你喜欢
      • 1970-01-01
      • 2012-03-03
      • 2011-01-28
      • 2012-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-13
      相关资源
      最近更新 更多