Отражение на C# и намиране на всички референции на клас/свойство в моето решение за проект

Имам клас на име Test и инстанцирах този клас в няколко други класа. Има ли някакъв начин да намеря всички препратки към класа "Fix" програмно. Знам, че мога да намеря това с 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 от 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 -> Find All References?


person Gifty    schedule 17.01.2018    source източник
comment
Дайте някакъв пример. И споделете вашите кодове, които сте предоставили.   -  person lucky    schedule 17.01.2018
comment
Здравей Storm, актуализирах въпроса си с пример.   -  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