Intellisense 在引用的项目中找不到生成的代码

问题描述 投票:0回答:1

我正在开发一个包含多个链接项目的大型代码库,因此我决定编写一些源代码生成器来自动生成一些样板代码。我的项目结构看起来像这样:

GeneratorProject (.NET standard 2.0 C# source generators)
^
CoreProject (.NET 8 C# class library)
^
UIProject (.NET 8 Blazor)

GeneratorProject 生成代码到 CoreProject 中,CoreProject 被 UIProject 使用。 CoreProject 中一切工作正常。例如:GeneratorProject 在 CoreProject 中创建一个名为

MyObjects
的静态类,并带有静态只读对象列表以方便使用。当我在 CoreProject 中编写代码时,我可以输入
MyObjects.
,Intellisense 将向我显示
MyObjects
中每个静态对象的列表。

我的问题:如果我在 UIProject 中输入代码,并且输入

MyObjects.
,则不会出现这样的建议列表。键入该内容时,即使只是
MyObjects
的建议也不会出现。如果我最终在
MyObjects
中输入有效的对象名称,它确实会被识别并编译(没有语法错误,并且将鼠标悬停在完全输入的名称上会像正常一样显示其定义)。

在输入时没有出现这些建议会破坏生成这些静态对象列表的便利性 - 该列表可能很长,并且在不输入建议的情况下,名称不是最容易记住的。这只是我使用生成器来说明问题的一个示例。

我怎样才能获得智能感知建议,向我显示由 UIProject 中的源生成器构建的对象?

我尝试过的事情:我可以在 CoreProject 中发出编译器生成的文件,并在构建时忽略这些文件。在研究如何解决这个问题时,这个想法来自这里:https://github.com/dotnet/roslyn/issues/50451#issuecomment-1609304299 我将其添加到

CoreProject.csproj

    <PropertyGroup>
        <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
        <CompilerGeneratedFilesOutputPath>$(ProjectDir)_generated</CompilerGeneratedFilesOutputPath>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
        <NoWarn>1701;1702</NoWarn>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
        <NoWarn>1701;1702</NoWarn>
    </PropertyGroup>
    <Target Name="SkipSourceGeneratedFiles" BeforeTargets="CoreCompile">
        <ItemGroup>
            <Compile Remove="_generated/**/*" />
        </ItemGroup>
    </Target>

这会导致我生成的所有文件都显示在解决方案资源管理器中的 _ generated 文件夹下。这确实使输入建议在 UIProject 中起作用,但出现了一个新问题:Visual Studio 会看到每个生成文件的两个副本,并在我引用生成文件中的某些内容的每个位置下显示错误(红色波形图)。所有错误都是

CS0229: Ambiguity between 'MyObjects.something' and 'MyObjects.something'
。该程序仍然可以正常构建和运行,因为 csproj 指示 _ generated 文件夹中的任何内容都被排除在构建之外,因此只有真正的生成器文件被构建。但现在大多数文件到处都有误报错误,这些错误在 Visual Studio 错误列表中与真实错误无法区分,这在与更大的团队合作时是不可接受的。但是,如果有一种方法可以在 Visual Studio 中抑制
CS0229
,那就足以解决我的问题,我可以使用它。

我尝试过的其他方法:我一直在尝试将 GeneratorProject 与 CoreProject 一起直接附加到 UIProject。这样我就可以在 CoreProject 和 UIProject 中创建生成的代码。生成器的工作方式与现在的 CoreProject 完全一样。但我会向生成器添加代码,以检测当前项目是否引用了引用 GeneratorProject 的程序集。如果是这样,它基本上会生成与为 CoreProject 生成的文件相同的文件,但为 UIProject 生成的文件将仅引用 CoreProject 中的文件。一个例子:

生成器正在 CoreProject 中创建此文件:

namespace CoreProject.GeneratorOutput;

public static class MyObjects
{
    public static readonly SomeObject something = new("this is an example");
}

当生成器在 UIProject 上运行时,它会检查 UIProject 是否引用了引用 GeneratorProject 的项目。确实如此 - 它找到了 CoreProject。在生成器中,我知道该生成器为 CoreProject 创建了什么。所以它会为 UIProject 生成类似这样的东西:

namespace UIProject.GeneratorOutput;

public static class MyObjects
{
    public SomeObject something => CoreProject.GeneratorOutput.MyObjects.something;
}

这种模式可以适用于静态类,这些静态类只是像这样的静态对象列表,尽管生成器代码必须变得有点难看。然而,这个

MyObjects
示例只是我拥有的一个生成器用例 - 我还有其他生成器可以执行诸如在非静态对象上生成属性之类的操作。这种模式对那些人不起作用 - 我必须做一些事情,比如生成一个继承自 CoreProject 类的类并稍微更改属性名称,这会变得非常难看并且不太可用。

底线:有人以前处理过这个问题,并且知道解决方法或修复吗?

有关技术细节:我使用的是 Visual Studio 2022 Enterprise 版本 17.9.5,我的核心和 UI 项目采用 C# 和 .NET 8,我的生成器项目使用 Microsoft.CodeAnalysis.CSharp 版本 4.6.0。如果有帮助,我很乐意提供更多信息!

c# visual-studio intellisense sourcegenerators
1个回答
0
投票

我能够重现您的问题:

您遇到的问题是由命名空间名称/类名称冲突引起的。

因此,有两种方法可以处理这种情况:

1、更改GeneratorProject中的类名CoreProject,例如:

using System;

namespace GeneratorProject
{
    public class Class1
    {

    }
    public static class Gen_CoreProject { //You can change this class name.
        public static void testmethod() { }
    }
}

之后就可以直接使用Gen_CoreProject类了,没有任何问题。

2、设置并使用命名空间的别名,例如:

using CoreProject;
using GenCore = GeneratorProject.CoreProject; //You can use this.
namespace UIProject
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");
            GenCore.testmethod(); //And you can use this.
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.