Roslyn C#:如何获取方法访问的所有字段和属性(及其所属类) [英] Roslyn C#: How to get all fields and properties (and their belonging class) accessed by a method

查看:28
本文介绍了Roslyn C#:如何获取方法访问的所有字段和属性(及其所属类)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望为我的方法计算对外部数据的访问指标.此外,我想知道我的方法从哪些对象访问字段和属性,以确定功能嫉妒代码异味的存在.

I wish to calculate the Access To Foreign Data metric for my methods. Furthermore, I would like to know from which objects my methods are accessing fields and properties to determine the existence of feature envy code smells.

对于这个例子:

public class DoctorService
{
    private List<Doctor> _doctors;
    public Doctor FindAvailableDoctor(DateRange timeSpan)
    {
        foreach (Doctor d in _doctors)
        {
            foreach(DateRange holiday in d.HolidayDates)
            {
                d.Test = null;
                if (!holiday.OverlapsWith(timeSpan)) return d;
            }
        }
        return null;
    }
}

,特别是 FindAvailableDoctor 方法,我想构建一个访问字段列表,其中包含 Doctor 类的 HolidayDates 和 Test 属性.我还想知道这两个属性都属于 Doctor 类(由类名及其命名空间标识).

and specifically the FindAvailableDoctor method, I would like to build a list of accessed fields that would contain the HolidayDates and Test property of the Doctor class. I would also like to know both these properties belong to the Doctor class (identified by the class name and its namespace).

我编写了以下代码来完成此操作:

I've made the following code to acomplish this:

var accessedFields = member.DescendantNodes().OfType<MemberAccessExpressionSyntax>();
foreach (var field in accessedFields)
{
    var symbol = semanticModel.GetSymbolInfo(field.Expression).Symbol;
    switch(symbol)
    {
        case ILocalSymbol local:
            fields.Add(new CaDETMember { Name = local.Type + "|" + local.Name });
            break;
        case IPropertySymbol prop:
            fields.Add(new CaDETMember { Name = prop.ContainingSymbol + "|" + field.ToString() });             
            break;
        case IParameterSymbol param:
            fields.Add(new CaDETMember { Name = param.Type + "|" + field.ToString() });
            break;
    };
}

并开始摆弄 Symbol API 的字段.然而,这个解决方案既不干净,我很确定会遗漏一些非平凡代码的边缘情况.

and have started fiddling about with the fields of the Symbol API. However, this solution is both unclean and I am pretty sure will miss some edge cases for non-trivial code.

提取方法访问的字段和属性名称的更好方法是什么,以便我也可以知道访问的字段和属性属于哪个类?

What would be a better way to extract the field and property names accessed by a method, so that I can also know which class the accessed fields and properties belong to?

根据杰森的回答,我采用了以下解决方案:

Based on Jason's answer, I went with the following solution:

var accessedFields = semanticModel.GetOperation(member).Descendants().OfType<IMemberReferenceOperation>();
foreach (var field in accessedFields)
{
    fields.Add(new CaDETMember {Name = field.Member.ToDisplayString()});
}
return fields;

推荐答案

你的方法实际上是一个非常好的方法,所以不要觉得太糟糕.还有第二种方法是使用 IOperation API.如果您调用 SemanticModel.GetOperation(),它会为您提供一个 IOperations 树,您可以遍历这些树,这些树表示在代码中的各个点执行的语义操作.特别是有一个 IMemberReferenceOperation 将指向到被引用的成员.所以就像:

Your approach is actually a perfectly fine approach, so don't feel too bad about it. There's a second way to do it which is to use the IOperation APIs. If you call SemanticModel.GetOperation() that gives you a tree of IOperations you can walk through which represent the semantic operations being performed at various points in the code. In particular there's an IMemberReferenceOperation that will point to the member being referenced. So something like:

var memberReferences = semanticModel.GetOperation(methodSyntax).Descendants().OfType<IMemberReferenceOperation>()

会让您查看这些,然后从那里获取符号.本地访问还有其他操作.

will let you look at those and then get the symbols from there. There's other operations for local accesses too.

这篇关于Roslyn C#:如何获取方法访问的所有字段和属性(及其所属类)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆