Использование компиляции на более поздних этапах конвейера генерацииC#

Место общения программистов C#
Ответить
Anonymous
 Использование компиляции на более поздних этапах конвейера генерации

Сообщение Anonymous »

Мой генератор должен найти все типы в проектах, на которые имеются ссылки, которые соответствуют определенным критериям, и сгенерировать класс для каждого из них, используя типы возвращаемых методов.
Пример входных данных (в проекте, на который ссылаются, а не в том, который ссылается на генератор):

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

class SuitableClass
{
public CustomType1 GetCustomType1() { ... }
public CustomType2 GetCustomType2() { ... }
}

class SuitableClass2
{
public CustomType3 GetCustomType4() { ... }
public CustomType4 GetCustomType4() { ... }
}
Пример вывода:

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

public class SuitableClassGenerated
{
public void Handle(CustomType1) { ... }
public void Handle(CustomType2) { ... }
}

public class SuitableClass2Generated
{
public void Handle(CustomType3) { ... }
public void Handle(CustomType4) { ... }
}
Код генератора:

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

public void Initialize(IncrementalGeneratorInitializationContext context)
{
IncrementalValuesProvider typeNames = context
.CompilationProvider
.SelectMany((c, _) => GetAllSupportedTypes(c.SourceModule.ReferencedAssemblySymbols)
.Select(x => x.ContainingNamespace.ToDisplayString() + "." + x.MetadataName));

IncrementalValuesProvider generationInput = typeNames
.Combine(context.CompilationProvider)
.Select((c, _) =>
{
var clientType = c.Right.GetTypeByMetadataName(c.Left);
if (clientType == null)
return default;
return new Info(clientType.Name,
clientType.GetMembers().OfType()
.Where(m => m is { DeclaredAccessibility: Accessibility.Public, IsStatic: false, ReturnsVoid: false })
.Select(m => m.ReturnType.ToDisplayString())
.ToImmutableArray());
})
.Where(x => x.Methods != null);

context.RegisterSourceOutput(generationInput,
(ctx, input) =>
{
var code = GenerateCode(input);
if (code != null)
ctx.AddSource($"{input.Name}.g.cs", code);
});
}

record struct Info(string Name, ImmutableArray Methods);
Как видите, эти два этапа требуют доступа к компиляции, что нарушает всю идею кэширования. Есть ли способ заставить кэширование работать так, чтобы некоторые этапы можно было пропустить? Например, если я добавляю метод с новым типом возвращаемого значения, мне нужно перезапустить только второй этап.
Есть ли способ переписать такой многоэтапный конвейер, связанный с компиляцией, чтобы сделать его более удобным для кэширования?

Подробнее здесь: https://stackoverflow.com/questions/782 ... n-pipeline
Ответить

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

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

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

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

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