My solution has the following shape:
Consumer/
Program.cs
MessageHandler.cs
...
SourceGenerator/
RabbitMQGenerator.cs
Domain/
Messages/
TestCommand.cs
TestEvent.cs
The Consumer
project has a project reference dependency to Domain
and it depends on the SourceGenerator
either via Nuget or project reference.
I am trying to build a source generator (using IIncrementalGenerator
) to register methods to consume RabbitMQ messages. The generator does the following:
- Looks for all message handlers (tagged with a specific attribute)
- Looks for all messages (tagged with a specific attribute)
- For each method in each message handler class, it look for the appropriate message type (because the message type defines the RabbitMQ queue) and register it for consumption.
If the Messages/
folder is in the Consumer
project, the source generator detects everything and works great. But if the messages are in the Domain
project, the source generator cannot access them and it fails.
I also tried adding the source generator as a dependency to the Domain
project, but that just resulted in the source generator running twice, once in each project, and not generating the desired outcome.
Basically, my generator takes part of the data needed from one project (or assembly), and the rest from another project. Is this behavior supported? If so, how can I accomplish it?
Here are my project files: Consumer:
<Project Sdk="Microsoft.NET.Sdk.Worker">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<!-- Other nuget dependencies -->
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Domain\Domain.csproj" />
<ProjectReference Include="..\SourceGenerator\SourceGenerator.csproj"
ReferenceOutputAssembly="false"
OutputItemType="Analyzer" />
</ItemGroup>
</Project>
Domain:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<!-- Other nuget dependencies -->
</ItemGroup>
</Project>
Source Generator:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>10.0</LangVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<IsRoslynComponent>true</IsRoslynComponent>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.6.0" />
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
</ItemGroup>
</Project>
Example of MessageHandler.cs
:
[EntityHandler]
public class MessageConsumer
{
[MessageHandler(typeof(TestCommand))]
public Task OnTestCommand(TestCommand command)
{
// ...
}
Example of TestCommand.cs
:
[MessageType("RabbitMQ.TestCommand")]
public class TestCommand : IRabbitMqCommand
{
// ...
}
I found this question that solves this issue for generators implementing the ISourceGenerator
interface, but I cannot find anything for IIncrementalGenerator
.