C# Roslyn如何查找/修改精简的Linq方法调用
我们正在使用Roslyn遍历代码库,替换数据库调用,并向以前进行调用的任何方法添加新的会话参数。例如:C# Roslyn如何查找/修改精简的Linq方法调用,c#,linq,roslyn,C#,Linq,Roslyn,我们正在使用Roslyn遍历代码库,替换数据库调用,并向以前进行调用的任何方法添加新的会话参数。例如: public bool Save(string someData) { // implementation here } // Becomes public bool Save(IDriveSession session, string someData) { } // And Invocations Go From Save("MyData"); // to Save(session, "
public bool Save(string someData) { // implementation here }
// Becomes
public bool Save(IDriveSession session, string someData) { }
// And Invocations Go From
Save("MyData");
// to
Save(session, "MyData");
public IEnumerable<Person> GetPeople(IEnumerable<Guid> ids)
{
return ids.Select(GetPerson);
}
// Should transform to
public IEnumerable<Person> GetPeople(IDriveSession session, IEnumerable<Guid> ids)
{
return ids.Select(x => GetPerson(session, x));
}
这是可行的,除了Linq调用,特别是那些已经减少的调用。例如:
public bool Save(string someData) { // implementation here }
// Becomes
public bool Save(IDriveSession session, string someData) { }
// And Invocations Go From
Save("MyData");
// to
Save(session, "MyData");
public IEnumerable<Person> GetPeople(IEnumerable<Guid> ids)
{
return ids.Select(GetPerson);
}
// Should transform to
public IEnumerable<Person> GetPeople(IDriveSession session, IEnumerable<Guid> ids)
{
return ids.Select(x => GetPerson(session, x));
}
适用的静态方法
public static IEnumerable<InvocationExpressionSyntax> GetMethodInvocationsMissingDriveSessionParameter(
SemanticModel semanticModel, SyntaxNode syntax) =>
syntax.DescendantNodes()
.OfType<InvocationExpressionSyntax>()
.Where(invocationExpressionSyntax => invocationExpressionSyntax.ArgumentList == null ||
!invocationExpressionSyntax.ArgumentList.Arguments.Any(a => a.ToString() == DriveSessionParameterName))
.Where(invocationExpressionSyntax => CallsMethodWithDriveSessionParameter(semanticModel, invocationExpressionSyntax));
// Child Nodes that have method calls with 0 arguments OR without session argument AND the method called takes a new Session Parm.
// * This may need to be recursive to find nested calls.
public static IEnumerable<ObjectCreationExpressionSyntax> GetObjectCreationsMissingDriveSessionParameter(
SemanticModel semanticModel, SyntaxNode syntax) =>
syntax.DescendantNodes()
.OfType<ObjectCreationExpressionSyntax>()
.Where(invocationExpressionSyntax => invocationExpressionSyntax.ArgumentList == null || !invocationExpressionSyntax.ArgumentList.Arguments.Any(a => a.ToString() == DriveSessionParameterName))
.Where(invocationExpressionSyntax => CallsMethodWithDriveSessionParameter(semanticModel, invocationExpressionSyntax));
//Determine if methods need session parm.
private static bool CallsMethodWithDriveSessionParameter(SemanticModel semanticModel, ExpressionSyntax syntax)
{
SymbolInfo symbolInfo;
symbolInfo = semanticModel.GetSymbolInfo(syntax);
return symbolInfo.CandidateSymbols
.OfType<IMethodSymbol>()
.Any(methodSymbol => methodSymbol.Parameters.Any(p => p.Type.Name == DriveSessionTypeName));
}
公共静态IEnumerable GetMethodInvocationsMissingDriveSessionParameter(
SemanticModel SemanticModel,SyntaxNode语法)=>
syntax.degenantNodes()
第()类
.Where(invocationExpressionSyntax=>invocationExpressionSyntax.ArgumentList==null | |
!invocationExpressionSyntax.ArgumentList.Arguments.Any(a=>a.ToString()==DriveSessionParameterName))
.Where(invocationExpressionSyntax=>CallsMethodWithDriveSessionParameter(semanticModel,invocationExpressionSyntax));
//具有带0个参数或不带会话参数的方法调用且被调用的方法采用新会话参数的子节点。
//*这可能需要递归才能找到嵌套调用。
公共静态IEnumerable GetObjectCreationAssingDriveSessionParameter(
SemanticModel SemanticModel,SyntaxNode语法)=>
syntax.degenantNodes()
第()类
.Where(invocationExpressionSyntax=>invocationExpressionSyntax.ArgumentList==null | | |!invocationExpressionSyntax.ArgumentList.Arguments.Any(a=>a.ToString()==DriveSessionParameterName))
.Where(invocationExpressionSyntax=>CallsMethodWithDriveSessionParameter(semanticModel,invocationExpressionSyntax));
//确定方法是否需要会话参数。
private static bool CallsMethodWithDriveSessionParameter(SemanticModel SemanticModel,ExpressionSyntax语法)
{
SymbolInfo SymbolInfo;
symbolInfo=semanticModel.GetSymbolInfo(语法);
返回符号info.CandidateSymbols
第()类
.Any(methodSymbol=>methodSymbol.Parameters.Any(p=>p.Type.Name==DriveSessionTypeName));
}
您是否记得,例如,您可以将委托变量分配给某个方法,并将其传递给Select
方法<代码>函数变量=过滤器;新[]{1}.Where(var)代码>所以您应该通过CFG并更改所有这些赋值、参数传递等等。第一步建议您尝试检索作用域中所有InvocationExpressionSyntax
节点的语义信息,并检查其接收方是否为System.Linq.Enumerable