Генератор источника не видит классов зависимого проектаC#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Генератор источника не видит классов зависимого проекта

Сообщение Anonymous »

У меня есть модульный монолит вместе с чистой архитектурой следующим образом:

Прикладные проекты зависит от доменных проектов, а конечные позиции находятся в проектах применения, в то время как в Enttities. Удаление конечных точек почти идентичны, поэтому я хотел создать Delete Endpoints с генерацией источников. Вот проблема:
Определение/абстракция объекта находится в общем. Домен Project:

Код: Выделить всё

public abstract class AuditableEntity : IAuditableEntity
{
....
}
и все проекты доменных модулей зависят от этого общего. domain , а все объекты получены из общего.domain.entitiety.Auditaitality . Пример объекта внутри инвентаризации модуль:

Код: Выделить всё

public class Product : AggregateRoot // AggregateRoot is derived from AuditableEntity so Product is an AuditableEntity
{
....
}
Таким образом, мой DeleteendPointSourceGenerator способен найти объекты, полученные из Audabletity , если он работает на доменных проектах, но не может найти ни одного из них, если он работает в проектах применения (как мне это нужно). Как я могу это решить?

Код: Выделить всё

[Generator]
public class DeleteEndpointSourceGenerator : ISourceGenerator
{
private const string AuditableEntityFullName = "Common.Domain.Entities.AuditableEntity";

public void Initialize(GeneratorInitializationContext context)
{
context.RegisterForSyntaxNotifications(() => new SyntaxReceiver());
}

public void Execute(GeneratorExecutionContext context)
{
if (context.SyntaxReceiver is not SyntaxReceiver receiver)
{
context.ReportDiagnostic(Diagnostic.Create(_noSyntaxReceiverDescriptor, Location.None));
return;
}

var compilation = context.Compilation;

var auditableEntitySymbol = compilation.GetTypeByMetadataName(AuditableEntityFullName);
if (auditableEntitySymbol == null)
{
context.ReportDiagnostic(Diagnostic.Create(_auditableEntityNotFoundDescriptor, Location.None));
return;
}

foreach (var classDeclaration in receiver.CandidateClasses)
{
var model = compilation.GetSemanticModel(classDeclaration.SyntaxTree);

if (model.GetDeclaredSymbol(classDeclaration) is not INamedTypeSymbol classSymbol)
{
continue;
}

if (!IsDerivedFrom(classSymbol, auditableEntitySymbol))
{
continue;
}

context.ReportDiagnostic(Diagnostic.Create(_classInheritsDescriptor, Location.None, classSymbol.Name, auditableEntitySymbol.Name));

var namespaceName = classSymbol.ContainingNamespace.ToDisplayString();
var className = classSymbol.Name;

var source = GenerateDeleteEndpointCode(namespaceName, className);
context.AddSource($"{className}_DeleteEndpoint.g.cs", SourceText.From(source, Encoding.UTF8));
context.ReportDiagnostic(Diagnostic.Create(_endpointGeneratedDescriptor, Location.None, className));
}
}

private static bool IsDerivedFrom(INamedTypeSymbol? classSymbol, INamedTypeSymbol baseTypeSymbol)
{
var currentType = classSymbol;
while (currentType != null)
{
if (SymbolEqualityComparer.Default.Equals(currentType, baseTypeSymbol))
{
return true;
}
currentType = currentType.BaseType;
}
return false;
}

private static string GenerateDeleteEndpointCode(string namespaceName, string className)
{
var pluralClassName = Pluralize(className);
return $@"
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Mvc;
using Common.Domain.ResultMonad;
using Common.Application.Auth;
using Common.Application.Extensions;
using Common.Application.Persistence;
using {namespaceName};
using Microsoft.Extensions.DependencyInjection;
using Common.Application.ModelBinders;
using Ardalis.Specification;

namespace SourceGenerated.Application.{pluralClassName}.v1.Delete;

internal static class {className}DeleteEndpoint
{{
internal static void MapEndpoint(RouteGroupBuilder apiGroup)
{{
apiGroup
.MapDelete(""{{id}}"", Delete{className}Async)
.WithDescription(""Delete a {className}."")
.MustHavePermission(CustomActions.Delete, CustomResources.{pluralClassName})
.Produces(StatusCodes.Status204NoContent)
.TransformResultToNoContentResponse();
}}

private sealed class {className}ByIdSpec : SingleResultSpecification
{{
public {className}ByIdSpec({className}Id id)
=> Query
.Where(p => p.Id == id);
}}

private static async Task Delete{className}Async(
[FromRoute, ModelBinder(typeof(StronglyTypedIdBinder))] {className}Id id,
[FromServices] IRepository repository,
[FromKeyedServices(nameof(Inventory))] IUnitOfWork unitOfWork,
CancellationToken cancellationToken)
=> await repository
.SingleOrDefaultAsResultAsync(new {className}ByIdSpec(id), cancellationToken)
.TapAsync(entity => repository.Delete(entity))
.TapAsync(async _ =>  await unitOfWork.SaveChangesAsync(cancellationToken));
}}
";
}

private static string Pluralize(string word)
{
if (word.EndsWith("y", StringComparison.OrdinalIgnoreCase))
{
return $"{word.Substring(0, word.Length - 1)}ies";
}

if (word.EndsWith("s", StringComparison.OrdinalIgnoreCase))
{
return $"{word}es";
}

return $"{word}s";
}

private sealed class SyntaxReceiver : ISyntaxReceiver
{
public List CandidateClasses { get; } = [];

public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
{
if (syntaxNode is ClassDeclarationSyntax classDeclarationSyntax)
{
CandidateClasses.Add(classDeclarationSyntax);
}
}
}

private static readonly DiagnosticDescriptor _noSyntaxReceiverDescriptor = new(
id: "GEN001",
title: "Syntax Receiver Not Found",
messageFormat: "Syntax receiver not found",
category: "SourceGenerator",
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true);

private static readonly DiagnosticDescriptor _auditableEntityNotFoundDescriptor = new(
id: "GEN002",
title: "AuditableEntity Not Found",
messageFormat: "AuditableEntity not found",
category: "SourceGenerator",
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true);

private static readonly DiagnosticDescriptor _endpointGeneratedDescriptor = new(
id: "GEN003",
title: "Endpoint Generated",
messageFormat: "Generated delete endpoint for {0}",
category: "SourceGenerator",
defaultSeverity: DiagnosticSeverity.Info,
isEnabledByDefault: true);

private static readonly DiagnosticDescriptor _classInheritsDescriptor = new(
id: "GEN004",
title: "Class Inherits AuditableEntity",
messageFormat: "{0} is derived from {1}",
category: "SourceGenerator",
defaultSeverity: DiagnosticSeverity.Info,
isEnabledByDefault: true);
}

Ожидаемое поведение:
Допустим, мы запускаем этот генератор источника на Inventory.application Project, он должен найти Inventory.domain объекты (объекты (он должен найти Inventory.domain (

Код: Выделить всё

Inventory.Application
имеет ссылку на Inventory.domain ), затем генерируйте эту конечную точку. Но это не может. Он находит только инвентаризацию. Domain объекты, если он работает на Inventory.domain .

Подробнее здесь: https://stackoverflow.com/questions/788 ... ts-classes
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Генератор исходного кода не будет видеть классы зависимого проекта.
    Anonymous » » в форуме C#
    0 Ответы
    7 Просмотры
    Последнее сообщение Anonymous
  • Xcode не видит мое устройство iOS, но iTunes видит
    Гость » » в форуме IOS
    0 Ответы
    121 Просмотры
    Последнее сообщение Гость
  • GDB не видит некоторые классы, но видит другие
    Гость » » в форуме C++
    0 Ответы
    97 Просмотры
    Последнее сообщение Гость
  • Xcode не видит мое устройство iOS, но iTunes видит
    Гость » » в форуме IOS
    0 Ответы
    95 Просмотры
    Последнее сообщение Гость
  • BIOS видит загрузочную флешку, но не видит загрузочный файл BIOS [закрыто]
    Anonymous » » в форуме Linux
    0 Ответы
    30 Просмотры
    Последнее сообщение Anonymous

Вернуться в «C#»