Partilhar via


Orleans geração de código

Antes da Orleans 7.0, a geração de código-fonte era mais manual e exigia intervenção explícita do desenvolvedor. A partir da Orleans versão 7.0, a geração de código é automática e normalmente não requer intervenção. No entanto, ainda existem casos em que influenciar na geração de código pode ser desejável, por exemplo, para gerar código para tipos não gerados automaticamente ou para tipos em outra biblioteca.

Habilitar a geração de código

Orleans gera código-fonte C# para o aplicativo em tempo de compilação. Todos os projetos, incluindo o host, precisam dos pacotes NuGet apropriados instalados para habilitar a geração de código. Estão disponíveis os seguintes pacotes:

Use o GenerateSerializerAttribute para especificar que o tipo se destina à serialização e que Orleans deve gerar código de serialização para ele. Para obter mais informações, consulte Usar Orleans serialização.

O runtime Orleans utiliza código gerado para garantir a adequada serialização dos tipos utilizados em todo o cluster e para gerar código boilerplate. Este esqueleto de código abstrai os detalhes de implementação do despacho de métodos, propagação de exceções e outros conceitos internos de execução. A geração de código pode ser executada ao criar projetos ou quando o aplicativo é inicializado.

Geração de código em tempo de compilação

No momento da compilação, Orleans gera código para todos os tipos marcados com GenerateSerializerAttribute. Se um tipo não estiver marcado com GenerateSerializer, Orleans não o serializará.

Se estiver desenvolvendo com F# ou Visual Basic, a geração de código também pode ser usada. Para obter mais informações, consulte estes exemplos:

Estes exemplos demonstram o uso do Orleans.GenerateCodeForDeclaringAssemblyAttribute, especificando tipos na assembly para que o gerador de código-fonte inspecione e gere código-fonte.

O método preferido para a geração de código é em tempo de compilação. Habilite a geração de código em tempo de compilação usando um dos seguintes pacotes:

  • Microsoft.Orleans.OrleansCodeGenerator.Build: Um pacote usando Roslyn para geração de código e .NET Reflection para análise.
  • Microsoft.Orleans.CodeGenerator.MSBuild: Um pacote de geração de código mais recente aproveitando o Roslyn para geração e análise de código. Ele não carrega binários de aplicativos, evitando problemas causados por versões de dependência conflitantes e estruturas de destino diferentes. Este gerador de código também melhora o suporte para compilações incrementais, resultando em tempos de compilação mais curtos.

Instale um desses pacotes em todos os projetos que contenham grãos, interfaces de grãos, serializadores personalizados ou tipos enviados entre grãos. A instalação de um pacote injeta um destino no projeto que gera código em tempo de compilação.

Ambos os pacotes (Microsoft.Orleans.CodeGenerator.MSBuild e Microsoft.Orleans.OrleansCodeGenerator.Build) suportam apenas projetos C#. Ofereça suporte a outras linguagens usando o Microsoft.Orleans.OrleansCodeGenerator pacote (descrito abaixo) ou criando um projeto C# atuando como destino para o código gerado a partir de assemblies escritos em outras linguagens.

Emita diagnósticos adicionais em tempo de compilação especificando um valor para OrleansCodeGenLogLevel no arquivo .csproj do projeto de destino. Por exemplo: <OrleansCodeGenLogLevel>Trace</OrleansCodeGenLogLevel>.

Geração de código em tempo de inicialização

No Orleans 7+, nada acontece durante a inicialização. A geração de código ocorre apenas no momento da compilação.

A geração de código pode ser realizada durante a inicialização no cliente e no silo instalando o Microsoft.Orleans.OrleansCodeGenerator pacote e usando o método de ApplicationPartManagerCodeGenExtensions.WithCodeGeneration extensão:

builder.ConfigureApplicationParts(
    parts => parts
        .AddApplicationPart(typeof(IRuntimeCodeGenGrain).Assembly)
        .WithCodeGeneration());

No exemplo anterior, builder pode ser uma instância de ISiloHostBuilder ou IClientBuilder. Passe uma instância opcional ILoggerFactory para WithCodeGeneration para habilitar o registo em log durante a geração de código, por exemplo:

ILoggerFactory codeGenLoggerFactory = new LoggerFactory();
codeGenLoggerFactory.AddProvider(new ConsoleLoggerProvider());
    builder.ConfigureApplicationParts(
        parts => parts
            .AddApplicationPart(typeof(IRuntimeCodeGenGrain).Assembly)
            .WithCodeGeneration(codeGenLoggerFactory));

Influenciar a geração de código

Ao aplicar GenerateSerializerAttribute a um tipo, o IdAttribute também pode ser aplicado para identificar exclusivamente o membro. Da mesma forma, um alias pode ser aplicado usando o AliasAttribute. Para obter mais informações sobre como influenciar a geração de código, consulte Usar Orleans serialização.

Durante a geração de código, a geração de código para um tipo específico pode ser influenciada. Orleans gera automaticamente código para interfaces de grão, classes de grão, estado de grão e tipos passados como argumentos em métodos de grão. Se um tipo não se encaixar nesses critérios, use os seguintes métodos para orientar ainda mais a geração de código.

Adicionar SerializableAttribute a um tipo instrui o gerador de código a gerar um serializador para ele.

Adicionar [assembly: GenerateSerializer(Type)] a um projeto instrui o gerador de código a tratar esse tipo como serializável. Isso causa um erro se um serializador não puder ser gerado para esse tipo (por exemplo, porque o tipo não está acessível). Este erro interrompe a compilação se a geração de código estiver habilitada. Este atributo também permite gerar código para tipos específicos de outro assembly.

[assembly: KnownType(Type)] também instrui o gerador de código a incluir um tipo específico (que pode ser de um assembly referenciado), mas não causa uma exceção se o tipo estiver inacessível.

Gerar serializadores para todos os subtipos

Adicionar KnownBaseTypeAttribute a uma interface ou classe instrui o gerador de código a gerar código de serialização para todos os tipos que herdam ou implementam esse tipo.

Gerar código para todos os tipos em outro assembly

Às vezes, o código gerado não pode ser incluído em um assembly específico no momento da compilação. Os exemplos incluem bibliotecas compartilhadas sem referência Orleans, assemblies escritos em linguagens diferentes de C# e assemblies para os quais o código-fonte não está disponível. Nesses casos, deve colocar o código gerado para esses conjuntos num assembly separado, que é referenciado durante a inicialização.

Para habilitar isso para um assembly:

  1. Crie um projeto C#.
  2. Instale o Microsoft.Orleans.CodeGenerator.MSBuild ou Microsoft.Orleans.OrleansCodeGenerator.Build pacote.
  3. Adicione uma referência ao assembly de destino.
  4. Adicione [assembly: KnownAssembly("OtherAssembly")] no nível superior de um arquivo C#.

O KnownAssemblyAttribute instrui o gerador de código a inspecionar o assembly especificado e gerar código para os tipos dentro dele. Esse atributo pode ser usado várias vezes dentro de um projeto.

Em seguida, adicione o assembly gerado ao cliente/silo durante a inicialização:

builder.ConfigureApplicationParts(
    parts => parts.AddApplicationPart("CodeGenAssembly"));

No exemplo anterior, builder pode ser uma instância de ISiloHostBuilder ou IClientBuilder.

KnownAssemblyAttribute tem uma propriedade opcional, TreatTypesAsSerializable. Defina isso para true instruir o gerador de código a agir como se todos os tipos dentro desse assembly fossem marcados como serializáveis.