Partager via


Génération de code Orleans

Avant Orleans la version 7.0, la génération de source était plus manuelle et nécessitait une intervention explicite du développeur. Orleans À compter de la version 7.0, la génération de code est automatique et ne nécessite généralement aucune intervention. Toutefois, il existe toujours des cas où l’influence de la génération de code peut être souhaitée, par exemple pour générer du code pour les types non générés automatiquement ou pour les types d’un autre assembly.

Activer la génération de code

Orleans génère du code source C# pour l'application pendant la compilation. Tous les projets, y compris l’hôte, ont besoin des packages NuGet appropriés installés pour activer la génération de code. Les packages suivants sont disponibles :

Utilisez l'GenerateSerializerAttribute pour spécifier que le type est destiné à la sérialisation et que Orleans doit générer du code de sérialisation pour le type. Pour plus d’informations, consultez Utiliser la sérialisation Orleans.

Le Orleans runtime utilise du code généré pour garantir la sérialisation appropriée des types utilisés dans le cluster et pour générer du code réutilisable. Ce modèle standard extrait les détails de l’implémentation du dispatching des méthodes, de la propagation des exceptions et d’autres concepts internes d’exécution. La génération de code peut être effectuée lors de la génération de projets ou lors de l’initialisation de l’application.

Génération de code au temps de compilation

Au moment de la génération, Orleans génère du code pour tous les types marqués avec GenerateSerializerAttribute. Si un type n’est pas marqué avec GenerateSerializer, Orleans ne le sérialise pas.

Si vous développez avec F# ou Visual Basic, la génération de code peut également être utilisée. Pour plus d’informations, consultez les exemples suivants :

Ces exemples illustrent l’utilisation de Orleans.GenerateCodeForDeclaringAssemblyAttribute, en spécifiant des types dans l'assembly pour que le générateur de code source puisse inspecter et générer du code source.

La méthode préférée pour la génération de code est pendant le temps de compilation. Activez la génération de code pendant la compilation à l’aide de l’un des packages suivants :

  • Microsoft.Orleans.OrleansCodeGenerator.Build: package utilisant Roslyn pour la génération de code et la réflexion .NET pour l’analyse.
  • Microsoft.Orleans.CodeGenerator.MSBuild: package de génération de code plus récent tirant parti de Roslyn pour la génération et l’analyse du code. Il ne charge pas les fichiers binaires d’application, ce qui évite les problèmes causés par des versions de dépendance en conflit et des frameworks cibles différents. Ce générateur de code améliore également la prise en charge des builds incrémentielles, ce qui entraîne des temps de génération plus courts.

Installez l’un de ces packages dans tous les projets comportant des grains, des interfaces de grain, des sérialiseurs personnalisés ou des types échangés entre les grains. L'installation d'un package injecte une cible dans le projet qui génère du code pendant le processus de build.

Les deux packages (Microsoft.Orleans.CodeGenerator.MSBuild et Microsoft.Orleans.OrleansCodeGenerator.Build) prennent uniquement en charge les projets C#. Prenez en charge d’autres langages à l’aide du Microsoft.Orleans.OrleansCodeGenerator package (décrit ci-dessous) ou en créant un projet C# agissant comme cible pour le code généré à partir d’assemblys écrits dans d’autres langues.

Émettez des diagnostics supplémentaires au moment de la génération en spécifiant une valeur dans OrleansCodeGenLogLevel le fichier .csproj du projet cible. Par exemple : <OrleansCodeGenLogLevel>Trace</OrleansCodeGenLogLevel>.

Génération de code au moment de l’initialisation

Dans les versions 7 et supérieures de Orleans, rien ne se passe pendant l’initialisation. La génération de code se produit uniquement au temps de compilation.

La génération de code peut être mise en œuvre pendant l’initialisation sur le client et le silo en installant le package Microsoft.Orleans.OrleansCodeGenerator et en utilisant la méthode d’extension ApplicationPartManagerCodeGenExtensions.WithCodeGeneration :

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

Dans l'exemple précédent, builder peut être une instance de soit ISiloHostBuilder soit IClientBuilder. Passez une instance facultative ILoggerFactory à WithCodeGeneration pour activer la journalisation pendant la génération de code, par exemple :

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

Influencer la génération de code

Lors de l'application de GenerateSerializerAttribute à un type, IdAttribute peut également être appliqué pour identifier de manière unique le membre. De même, un alias peut être appliqué à l’aide du AliasAttribute. Pour plus d’informations sur l’influence sur la génération de code, consultez Utiliser la sérialisation Orleans.

Pendant la génération du code, la génération de code d’un type spécifique peut être influencée. Orleans génère automatiquement du code pour les interfaces de grain, les classes de grain, l’état du grain et les types passés en tant qu’arguments dans les méthodes de grain. Si un type ne correspond pas à ces critères, utilisez les méthodes suivantes pour guider la génération de code plus loin.

L’ajout SerializableAttribute à un type indique au générateur de code de générer un sérialiseur pour celui-ci.

L’ajout [assembly: GenerateSerializer(Type)] à un projet indique au générateur de code de traiter ce type comme sérialisable. Cela provoque une erreur si un sérialiseur ne peut pas être généré pour ce type (par exemple, parce que le type n’est pas accessible). Cette erreur interrompt la génération si la génération de code est activée. Cet attribut permet aussi de générer du code pour des types spécifiques issus d’un autre assembly.

[assembly: KnownType(Type)] indique également au générateur de code d’inclure un type spécifique (qui peut provenir d’un assembly référencé), mais il n’entraîne pas d’exception si le type est inaccessible.

Générer des sérialiseurs pour tous les sous-types

L’ajout KnownBaseTypeAttribute à une interface ou à une classe indique au générateur de code de générer du code de sérialisation pour tous les types qui héritent ou implémentent ce type.

Générer du code pour tous les types d’un autre assembly

Parfois, le code généré ne peut pas être inclus dans un assembly particulier au moment de la génération. Par exemple, les bibliothèques partagées ne référencent Orleanspas, les assemblys écrits dans des langages autres que C# et les assemblys pour lesquels le code source n’est pas disponible. Dans ces cas, placez le code généré pour ces assemblys dans un assembly distinct référencé lors de l’initialisation.

Pour activer cette option pour un assembly :

  1. Créez un projet C#.
  2. Installez le package Microsoft.Orleans.CodeGenerator.MSBuild ou Microsoft.Orleans.OrleansCodeGenerator.Build.
  3. Ajoutez une référence à l’assembly cible.
  4. Ajoutez [assembly: KnownAssembly("OtherAssembly")] au niveau supérieur d’un fichier C#.

KnownAssemblyAttribute donne instruction au générateur de code d’inspecter l’assembly spécifié et de générer du code pour les types qu’il contient. Cet attribut peut être utilisé plusieurs fois dans un projet.

Ensuite, ajoutez l’assembly généré au client/silo lors de l’initialisation :

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

Dans l'exemple précédent, builder peut être une instance de soit ISiloHostBuilder soit IClientBuilder.

KnownAssemblyAttribute a une propriété facultative, TreatTypesAsSerializable. Définissez cela à true pour que le générateur de code se comporte comme si tous les types de cet assemblage étaient marqués comme sérialisables.