C#反射并在我的项目解决方案中查找类/属性的所有引用

时间:2018-01-17 05:23:14

标签: c# reflection

我有一个名为Test的类,我在其他几个类中实例化了该类。有没有什么办法可以编程方式找到对“修复”类的所有引用。我知道我可以通过VisualStudio中的Find All References找到它,但我希望以编程方式满足我的要求。请帮忙。

示例: Fix.cs

namespace Testing
{
    public class Fix
    {
        public string fixName = "Name";
    }
}

CodeFix.cs

namespace Testing
{
    public class CodeFix
    {
        private string GetName()
        {
            Fix fix = new Fix();
            return fix.fixName;
        }
    }
}

现在我想在我的解决方案(命名空间测试)中编写代码来查找变量"fixName"的所有引用。 有没有什么办法可以以编程方式为类或变量实现此目的。我想用fileName和变量引用代码行来获得结果。

示例:

Result
{
FileName="CodeFix.cs",
Line=return fix.fixName;
}

我应该 自动执行以下方案 ,我需要查找所有参考资料。 我应该 不使用公共字段 ,所以当我找到像“fixName”这样的公共字段时,我应该将fixName从public更改为private,然后 公开同样使用属性

private string fixName;
public string FixName
{
    get { return fixName; }
    set { fixName = value; }
}

所以我应该更改文件codeFix.cs - 必须使用属性名return fix.fixName;更改行return fix.FixName;

我有一个VSIX项目来修复代码违规,我需要实现这个“自动修复”以避免使用公共字段。任何机会有没有办法获得Visual Studio - >查找所有参考数据?

1 个答案:

答案 0 :(得分:0)

有一种方法可以使用Roslyn编写可以检查源代码的单元测试。

对于测试项目,我使用xUnitBuildalyzer(它本身引用了Microsoft.CodeAnalysis个包),这样我的test.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Buildalyzer" Version="0.2.2" />
    <PackageReference Include="Buildalyzer.Workspaces" Version="0.2.2" />
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
    <PackageReference Include="xunit" Version="2.3.1" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
    <DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
  </ItemGroup>
</Project>

现在只有一个单元测试:

public class UnitTest1
{
    private readonly List<Document> _documents;

    public UnitTest1()
    {
        var projPath = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), "..", "..", "..", "CodeFixDemoTests.csproj"));
        AnalyzerManager manager = new AnalyzerManager();
        ProjectAnalyzer analyzer = manager.GetProject(projPath);
        AdhocWorkspace workspace = analyzer.GetWorkspace();
        _documents = new List<Document>();
        foreach (var projectId in workspace.CurrentSolution.ProjectIds)
        {
            var project = workspace.CurrentSolution.GetProject(projectId);
            foreach (var documentId in project.DocumentIds)
            {
                var document = workspace.CurrentSolution.GetDocument(documentId);
                if (document.SupportsSyntaxTree)
                {
                    _documents.Add(document);
                }
            }
        }
    }

    public string _myField;

    [Fact]
    public void NoPublicFields()
    {
        var classes = _documents.Select(doc => new { doc, classes = doc.GetSyntaxRootAsync().Result.DescendantNodes().OfType<ClassDeclarationSyntax>() })
            .SelectMany(doc => doc.classes.Select(@class => new { @class, doc.doc }));

        foreach (var classDeclaration in classes)
        {
            var classFields = classDeclaration.@class.DescendantNodes().OfType<FieldDeclarationSyntax>();
            foreach (var field in classFields)
            {
                var fieldHasPrivateModifier = field.Modifiers.Any(modifier => modifier.IsKind(Microsoft.CodeAnalysis.CSharp.SyntaxKind.PrivateKeyword));
                if (!fieldHasPrivateModifier)
                {
                    var errorMessage = $"Public field in class: \"{classDeclaration.@class.Identifier}\", File: {classDeclaration.doc.FilePath}";
                    Assert.True(false, errorMessage);
                }
            }
        }
    }
}

运行时提供以下输出:

Unit test failure

(找到的错误是测试类本身的public string _myField;

请确保为其提供csproj文件的正确路径,您应该好好去。如果你想将所有错误分开,你可以重构它以使用xUnit Theory而不是Fact,它将所有类声明作为输入。