Отражение С# и поиск всех ссылок на класс/свойство в моем проекте

У меня есть класс с именем Test, и я создал экземпляр этого класса в нескольких других классах. Есть ли способ программно найти все ссылки на класс «Исправить». Я знаю, что могу найти это с помощью Find All References в VisualStudio, но я хочу добиться этого программно для своего требования. Любая помощь, пожалуйста.

Пример: 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" в моем решении (тестирование пространства имен). Могу ли я каким-либо образом добиться этого программно либо для класса, либо для переменной. Я хотел бы получить результат с именем файла и строкой кода, на которую ссылается переменная.

Пример:

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

Я должен автоматизировать приведенный ниже сценарий, для которого мне нужно найти все ссылки. Мне следует не использовать общедоступные поля, поэтому, когда я нахожу общедоступное поле, такое как "fixName", я должен изменить fixName с общедоступного на приватное, а затем открыть то же самое с использованием свойства.

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

поэтому я должен изменить файл codeFix.cs - строка return fix.fixName;должна быть изменена с именем свойства return fix.FixName;.

У меня есть проект VSIX для исправления нарушения кода. Мне нужно реализовать это "автоматическое исправление", чтобы избежать использования общедоступных полей. Случайно ли есть способ получить данные Visual Studio -> Find All References?


person Gifty    schedule 17.01.2018    source источник
comment
Приведите какой-нибудь пример. И поделитесь своими кодами, которые вы предоставили.   -  person lucky    schedule 17.01.2018
comment
Привет, Шторм, обновил мой вопрос примером.   -  person Gifty    schedule 17.01.2018
comment
Для меня это похоже на XY-проблему. Приведенный выше код мало чем помогает, тем более что там нет класса Test. Более того, выполнение этого во время работы вашей программы имеет сомнительную ценность. Какова бы ни была причина, которая заставила вас думать, что вы хотите иметь возможность сделать это, я подозреваю, что есть другой, гораздо лучший способ сделать это.   -  person Peter Duniho    schedule 17.01.2018
comment
Извините за путаницу. Теперь я четко обновил свой вопрос.   -  person Gifty    schedule 17.01.2018


Ответы (1)


Существует способ использовать Roslyn для написания модульных тестов, которые могут проверять ваш исходный код.

Для тестового проекта я использую xUnit и Buildalyzer (которые сами ссылаются на пакеты 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 = [email protected]().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: \"{[email protected]}\", File: {classDeclaration.doc.FilePath}";
                    Assert.True(false, errorMessage);
                }
            }
        }
    }
}

Что дает следующий вывод при запуске:

Ошибка модульного теста

(Обнаруженная ошибка - это public string _myField; в самом тестовом классе)

Просто убедитесь, что вы указали правильный путь к вашему файлу csproj, и все будет готово. Если вы хотите разделить все ошибки, вы можете реорганизовать его, чтобы использовать xUnit Theory вместо Fact, который принимает все объявления классов в качестве входных данных.

person GeorgDangl    schedule 17.01.2018
comment
У меня есть проект VSIX для исправления нарушения кода, мне нужно реализовать это автоматическое исправление, чтобы избежать использования общедоступных полей. Случайно ли есть способ получить данные Visual Studio -> Find All References? - person Gifty; 17.01.2018
comment
Я бы порекомендовал вам взглянуть на проект xunit.analyzers: github.com/xunit/xunit. анализаторы для создания такой функциональности. Это не то, что я делал раньше, извините, я думал, что вы просто спрашиваете об обнаружении дефектов кода. - person GeorgDangl; 17.01.2018