是否可以使用将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等方法。任何人都可以向我展示使用方法吗?
谢谢!
答案 0 :(得分: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电动工具的与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();
}