Partilhar via


Orleans geração de código

Antes da Orleans 7.0, a geração de código-fonte era muito 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 não requer intervenção do desenvolvedor. No entanto, ainda há casos em que os desenvolvedores podem querer influenciar a geração de código, por exemplo, para gerar código para tipos que não são gerados automaticamente ou para gerar código para tipos em outro assembly.

Habilitar a geração de código

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

Use o para especificar que o tipo deve ser serializado e que o GenerateSerializerAttribute código de serialização deve ser gerado para o tipo. Para obter mais informações, consulte Usar Orleans serialização.

O Orleans tempo de execução faz uso do código gerado para garantir a serialização adequada de tipos que são usados em todo o cluster, bem como para gerar clichês, o que abstrai os detalhes de implementação de envio de método, propagação de exceção e outros conceitos internos de tempo de execução. A geração de código pode ser executada quando seus projetos estão sendo criados ou quando seu aplicativo é inicializado.

O que acontece durante a construçã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, ele não será serializado pelo Orleans.

Se você estiver desenvolvendo com F# ou Visual Basic, também poderá usar a geração de código. Para obter mais informações, consulte os seguintes exemplos:

Estes exemplos demonstram como consumir o Orleans.GenerateCodeForDeclaringAssemblyAttribute, especificando tipos no conjunto para os quais o gerador de origem deve inspecionar e gerar a fonte.

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

  • Microsoft.Orleans. OrleansCodeGenerator.Build. Um pacote que usa Roslyn para geração de código e usa o .NET Reflection para análise.
  • Microsoft.Orleans. CodeGenerator.MSBuild. Um novo pacote de geração de código que aproveita o Roslyn tanto para geração de código quanto para análise de código. Ele não carrega binários de aplicativos e, como resultado, evita problemas causados por versões de dependência conflitantes e estruturas de destino diferentes. O novo gerador de código também melhora o suporte para compilações incrementais, o que deve resultar em tempos de compilação mais curtos.

Um desses pacotes deve ser instalado em todos os projetos que contêm grãos, interfaces de grãos, serializadores personalizados ou tipos que são enviados entre grãos. A instalação de um pacote injeta um destino no projeto que gerará código no momento da compilação.

Ambos os pacotes (Microsoft.Orleans.CodeGenerator.MSBuild e Microsoft.Orleans.OrleansCodeGenerator.Build) suportam apenas projetos C#. Outras linguagens são suportadas usando o Microsoft.Orleans.OrleansCodeGenerator pacote descrito abaixo ou criando um projeto C# que pode atuar como o destino para o código gerado a partir de assemblies escritos em outras linguagens.

Diagnósticos adicionais podem ser emitidos em tempo de compilação, especificando um valor para OrleansCodeGenLogLevel no arquivo .csproj do projeto de destino. Por exemplo, <OrleansCodeGenLogLevel>Trace</OrleansCodeGenLogLevel>.

O que acontece durante a inicialização?

No Orleans 7+, nada acontece durante a inicialização. A geração de código é realizada em tempo de 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 acima, builder pode ser uma instância de qualquer um ISiloHostBuilder ou IClientBuilder. Uma instância opcional ILoggerFactory pode ser passada para WithCodeGeneration habilitar o registro 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, você também pode aplicar o IdAttribute para identificar exclusivamente o membro. Da mesma forma, você também pode aplicar um alias com 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, você pode influenciar a geração de código para um tipo específico. O código é gerado automaticamente 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 atender a esses critérios, os métodos a seguir podem ser usados 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 esse tipo.

Adicionar [assembly: GenerateSerializer(Type)] a um projeto instrui o gerador de código a tratar esse tipo como serializável e causará 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 interromperá uma compilação se a geração de código estiver ativada. 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/implementam esse tipo.

Gerar código para todos os tipos em outro assembly

Há casos em que o código gerado não pode ser incluído em um assembly específico no momento da compilação. Por exemplo, isso pode incluir bibliotecas compartilhadas que não fazem referência Orleansa assemblies escritos em linguagens diferentes de C# e assemblies nos quais o desenvolvedor não tem o código-fonte. Nesses casos, o código gerado para esses assemblies pode ser colocado em um 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 o 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. O atributo pode ser usado várias vezes dentro de um projeto.

O assembly gerado deve ser adicionado ao cliente/silo durante a inicialização:

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

No exemplo acima, builder pode ser uma instância de qualquer um ISiloHostBuilder ou IClientBuilder.

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