我想生成一个静态类,它应该有一个方法,具体取决于特定参考程序集中的其他类。
一个简化的例子:
// Generator.csproj
[Generator]
public class MyGenerator : ISourceGenerator
{
public void Initialize(GeneratorInitializationContext context)
{
// Register a factory that can create our custom syntax receiver
context.RegisterForSyntaxNotifications(() => new MySyntaxReceiver());
}
public void Execute(GeneratorExecutionContext context)
{
// var syntaxReceiver = (MySyntaxReceiver)context.SyntaxReceiver;
}
}
private class MySyntaxReceiver : ISyntaxReceiver
{
....
}
Run Code Online (Sandbox Code Playgroud)
// Core.csproj
// namespace Core.Entities
class Entity1 : IAccessControl {}
class Entity2 {}
class Entity3 : IAccessControl {}
Run Code Online (Sandbox Code Playgroud)
// Persistence.csproj => has a reference to Core …Run Code Online (Sandbox Code Playgroud) 我创建了一个源生成器来扩展满足某些条件的(部分)类。为了检查和查看生成的代码,我通过将以下内容添加到我的项目中来启用这些文件的发射:
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)
只要我不进行重构(例如重命名类),这就有效。因为对于每个类,当我重命名“源”类时,都会生成一个文件,但不会删除该文件。
所以我添加了以下代码来清理所有生成的文件(在清理和重建时)
<Target Name="CleanSourceGeneratedFiles" AfterTargets="Clean">
<RemoveDir Directories="Generated" />
</Target>
Run Code Online (Sandbox Code Playgroud)
然而,每次重建都会失败:
Error CS2001 Source file 'xyz.generated.cs' could not be found.
因此,我正在寻找另一种方法来使生成的源代码保持最新,该项目不仅会在每次尝试时进行编译。
我尝试根据MS Docs:How to use source Generation in System.Text.Json 来实现基于源生成的 JSON 序列化。我的代码如下:
using System;
using System.Text.Json;
var person = new Person(){FirstName = "John", LastName = "Shepard"};
Console.WriteLine(JsonSerializer.Serialize(person));
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
和我的 SerializationContext:
[JsonSerializable(typeof(Person))]
public partial class PersonJsonContext : JsonSerializerContext
{
}
Run Code Online (Sandbox Code Playgroud)
System.Text.Json我的项目中安装了 6.0.0 版本。
但是运行时dotnet build,我的类中没有生成任何代码PersonJsonContext。在哪里可以找到生成的代码?
我正在尝试使用C# 源生成器。我花了大约一天的时间,我发现这是一次非常令人沮丧和痛苦的经历。IntelliSense 极其不可靠。它偶尔会起作用,但大多数情况下不会起作用,而且我无法找出任何系统。(重新启动 Visual Studio 没有帮助。)
但更根本的是,我在调试生成的代码中的错误时遇到了很大的麻烦。当我在源生成器中的模板中犯错误并尝试编译时,我可能会在生成的文件中收到诸如“方法必须有返回类型”之类的错误。但是当我双击错误时,它不会将我带到生成的代码。这使得很难看出它出了什么问题。
有什么窍门吗?当编译失败时,有什么方法可以检查生成的代码吗?更一般地说,生成的代码何时可用于 IntelliSense,何时不可用,由什么决定?
我使用的是 Visual Studio Professional 2022 版本 17.1.6 和 ReSharper 2022.1。
提前致谢!
我有一个依赖于源生成器才能正常工作的库。在 中MyLibrary.csproj,我像这样引用生成器。
<ItemGroup>
<ProjectReference
Include="..\MyLibrary.Generators\MyLibrary.Generators.csproj"
PrivateAssets="contentfiles;build"
ReferenceOutputAssembly="false"
OutputItemType="analyzer"/>
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)
我需要这个分析器引用是可传递的,即该引用的项目MyLibrary应该可以MyLibrary.Generators传递地获取分析器。
像这样的简单参考似乎没有参考分析器,只是 MyLibrary
<ProjectReference Include="..\MyLibrary\MyLibrary.csproj" />
Run Code Online (Sandbox Code Playgroud)
我想强调的是,我不是在寻找MyLibrary.Generators作为常规程序集参考使用的,而是作为Roslyn 分析器使用的,因此我的源代码生成器可以在编译期间按预期运行。
我有一个 C# 9.0 源代码生成器,它引用一个类库,该类库包含一个用于标识要处理的类的属性。我现在正在编写单元测试,如下所述:
Compilation inputCompilation = CreateCompilation(@"
using Dependncy;
namespace MyCode
{
[Marker]
public partial class SimpleObject
{
[PropertyMarker(0)]
public int Test{get;set;}
}
}
");
var generator = new MyCodeGen();
// Create the driver that will control the generation, passing in our generator
GeneratorDriver driver = CSharpGeneratorDriver.Create(generator);
// Run the generation pass
// (Note: the generator driver itself is immutable, and all calls return an updated version of the driver that you should use for subsequent calls) …Run Code Online (Sandbox Code Playgroud) 我正在尽可能地复制Microsoft 网站示例中的所有内容,但没有生成任何内容。我创建了一个 MCVE 来尝试找出发生以下错误的原因:
Warning CS8034
Unable to load Analyzer assembly C:\Users\me\source\repos\SourceGenTest\SourceGenerators\bin\Debug\netstandard2.0\SourceGenerators.dll:
Could not find file 'C:\Users\me\source\repos\SourceGenTest\SourceGenerators\bin\Debug\netstandard2.0\SourceGenerators.dll'.
SourceGenLibrary 1 Active
Run Code Online (Sandbox Code Playgroud)
我已经检查了提供的路径,并且SourceGenerators.dll存在。这个错误对我来说毫无意义。
注意:在我提供的 MCVE 中,显然没有构建警告。不知道为什么,但源生成器仍然没有输出。
我的目标是拥有这样的工作流程:
SourceGenerators (class library)
is consumed by
SourceGenLibrary (class library)
is consumed by
SourceGenConsole (Console project)
Run Code Online (Sandbox Code Playgroud)
我希望分析器在类库中生成将在许多项目之间共享的定义。上述工作流程将其简化为一个依赖于一个库的项目,该库依赖于源生成器以尽可能保持 MCVE。
因为复制所有这些东西很烦人,如果你懒的话,这里有一个上传链接:下载链接 MCVE(据说发布后一周到期,但来源如下)。
相关信息:
$ dotnet --version
5.0.201
$ dotnet --list-sdks
5.0.103 [C:\Program Files\dotnet\sdk]
5.0.201 [C:\Program Files\dotnet\sdk]
Run Code Online (Sandbox Code Playgroud)
这些是源文件及其包含的内容。
/SourceGenTest.sln
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 …Run Code Online (Sandbox Code Playgroud) 我写了一个 SourceGenerator,但是如何测试它呢?
主要问题是如何模仿GeneratorExecutionContext(或在Compilation其中)哪个生成器进入Execute方法。我认为有一种正确的方法可以为单元测试制作假语法树,但我找不到它。有很多关于源生成器本身的文章,但没有一篇解释如何测试生成器。
我正在开发一个使用 C# 9 的源生成器的项目,但是当生成代码时,我希望将生成的代码的不同文件发送到生成代码的现有项目中的特定文件路径/位置。
这可能吗?我知道我可以指定它们全部放入的文件夹:
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
并将“生成”更改为我希望生成的文件位于其中的文件夹。就像我已经有一个名为“模型”的文件夹一样,我知道我会将“生成”更改为“模型”,然后将其放在那里。
但是,一旦它位于该文件路径内,它就会被放入一个名称为源生成器的项目名称的文件夹中,然后放入另一个名为 namespace.generatorclassname 的文件夹中。
所以在这种情况下,我所发生的事情是:
这是我当前发生的上述场景的屏幕截图: 生成的文件夹结构的屏幕截图
但是,如果我希望将每个文件生成到目标项目预先存在的文件夹结构中的不同位置,该怎么办?那可能吗?有任何想法吗?
我正在编写一个源生成器,但正在努力获取传递给属性构造函数的参数值。
我将以下内容注入到编译中:
namespace Richiban.Cmdr
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class CmdrMethod : System.Attribute
{
private readonly string _alias;
public CmdrMethod(string alias)
{
_alias = alias;
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后在我的示例应用程序中我有以下内容:
public static class InnerContainerClass
{
[CmdrMethod("test")]
public static void AnotherMethod(Data data)
{
Console.WriteLine($"In {nameof(AnotherMethod)}, {new { data }}");
}
}
Run Code Online (Sandbox Code Playgroud)
编译时没有错误或警告,并且我成功地找到了用我的CmdrMethod属性修饰的所有方法,但我无法获取传递给属性的值,因为由于某种原因,该ConstructorArguments属性的属性为空:
private static ImmutableArray<string> GetAttributeArguments(
IMethodSymbol methodSymbol,
string attributeName)
{
var attr = methodSymbol
.GetAttributes()
.Single(a => a.AttributeClass?.Name == attributeName);
var arguments = attr.ConstructorArguments;
if (methodSymbol.Name …Run Code Online (Sandbox Code Playgroud)