【问题标题】:Port NDepend CQLINQ query to c# LINQ端口 NDepend CQLINQ 查询到 c# LINQ
【发布时间】:2013-10-05 20:24:37
【问题描述】:

是否可以使用将 CQLinq 查询移植到简单的 C# LINQ 查询?

我正在使用 NDepend API 创建一个代码分析器工具,并且我想使用 CQLinq 查询。

有些很容易移植。例如,

from m in Methods
where m.ILCyclomaticComplexity > 10 
orderby m.ILCyclomaticComplexity descending
select new { m }

很容易移植到

using NDepend.CodeModel;
using NDepend.CodeQuery;

public List<IMethod> GetUnitTestFromType(ICodeBase codeBase)
{
    var complexMethods = (from m in codeBase.Application.Methods
                      where m.ILCyclomaticComplexity > 10
                      orderby m.ILCyclomaticComplexity descending
                      select m).ToList();
    return complexMethods;
} 

但我想使用更强大的 CQLinq 方法,即 AllowNoMatch()

from t in codeBase.Application.Types
where t.Implement("System.IDisposable".AllowNoMatch())
select t;

其实直接用CQLinq查询就好了。怎么样?

我可以看到有一个 NDepend.CodeQuery 命名空间,其中包含 CreateQuery、Compile 和 Execute 等方法。谁能给我一个用法示例吗?

谢谢!

【问题讨论】:

    标签: api ndepend cqlinq


    【解决方案1】:

    CQLinq 确实提供了许多在命名空间NDepend.Reserved.CQLinq 中定义的便捷扩展方法。这些扩展方法在 CQLinq 编译后时得到特殊处理,并且本身在 C# 中不可用。

    在 CQLinq 查询中编写时:t.Implement("System.IDisposable".AllowNoMatch())

    ...特殊的ExtensionMethodsCQLinqDependency.Implement() 扩展方法已解决。 CQLinq post-C#-compilation/pre-execution 步骤尝试在执行前解析指定为字符串 ("System.IDisposable".AllowNoMatch()) 的类型一次,并在 IType 上推断谓词。

    • 如果未找到全名为 "System.IDisposable" 的类型,则始终返回 false
    • 如果找到一个全名为"System.IDisposable" 的类型,则返回true。对于实现它的类型。

    ExtensionMethodsCQLinqDependency.Implement()的文档中规定该方法只能在ICQLinqExecutionContext中调用,否则必须调用NDepend.CodeModel.IType.NDepend.CodeModel.IType.Implement方法。

    因此,通过使用 NDepend.API,您必须自己完成 CQLinq 后编译工作,但这非常直接:

    var iDisposable = codebase.Types.SingleOrDefault(t.FullName == "System.IDisposable");
    if(iDisposable == null) {
      return new IType[0];
    }
    return from t in codeBase.Application.Types
           where t.Implement(iDisposable)
           select t;
    

    我可以看到有一个 NDepend.CodeQuery 命名空间,其中包含 CreateQuery、Compile 和 Execute 等方法。谁能给我一个用法示例吗?

    确实,使用 NDepend.API,您可以编译 CQLinq 查询字符串,执行它并使用结果。 OSS Power Tools 使用 CQLinq 查询代码$NDependRedistributable$\NDepend.PowerTools\CodeQueryConsole\CodeQueryConsolePowerTool.cs

    中提供了一个示例用法
         var codeBase = analysisResult.CodeBase;
         Func<string, IQueryCompiled> compileQueryProc = queryString => queryString.Compile( codeBase);
    
         // ... but if we can get a compareContext, then compile and execute the query against the compareContext
         ICompareContext compareContext;
         if (ProjectAnalysisUtils.TryGetCompareContextDefinedByBaseline(analysisResult, out compareContext)) {
            Debug.Assert(compareContext != null);
            compileQueryProc = queryString => queryString.Compile(compareContext);
         }
    
    ...
           IQueryCompiled queryCompiled;
           using (var queryEditSession = new QueryEditSession(queriesPreviouslyEdited)) {
               var queryString = queryEditSession.GetQueryString();
    COMPILE_QUERY:
               Console.BackgroundColor = ConsoleColor.Black;
               Console.ForegroundColor = ConsoleColor.White;
               if (queryString == null) { break; }
    
               // Try compile query
               queryCompiled = compileQueryProc(queryString);
               var queryCompiledError = queryCompiled.QueryCompiledError;
               if (queryCompiledError != null) {
                  queryString = queryEditSession.ShowCompilatioErrorsAndThenGetQueryString(queryCompiledError);
                  goto COMPILE_QUERY;
               }
            }
    
            // Execute query compiled
            var queryCompiledSuccess = queryCompiled.QueryCompiledSuccess;
            Debug.Assert(queryCompiledSuccess != null);
            var result = queryCompiledSuccess.Execute();
            if (result.Status != QueryExecutionStatus.Success) {
               var exception = result.Exception;
               // The error must be an Exception thrown by the query, since we don't use the Execute(...) overload with time-out!
               Debug.Assert(exception != null);
               DisplayQueryThrowAnException(exception);
               continue;
            }
    
            QueryExecutionResultDisplayer.Go(result.SuccessResult);
            Console.WriteLine();
         }
    

    【讨论】:

    • 谢谢!这是我需要的起点,来自 NDepend.CodeQuery 命名空间的字符串的扩展方法:“编译”! ndepend.com/api/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多