Expressions C#

À compter de .NET Framework 4.5, les expressions C# sont prises en charge dans Windows Workflow Foundation (WF). Les projets de workflow en C# créés dans Visual Studio 2012 qui ciblent .NET Framework 4.5 utilisent les expressions C#, et les projets de workflow en Visual Basic utilisent les expressions Visual Basic. Les projets de workflow .NET Framework 4 existants qui utilisent des expressions Visual Basic peuvent être migrés vers .NET Framework 4.6.1 indépendamment du langage de projet et sont pris en charge. Cette rubrique fournit une vue d’ensemble des expressions C# dans WF.

Utilisation des expressions C# dans les workflows

Utilisation des expressions C# dans Workflow Designer

À compter de .NET Framework 4.5, les expressions C# sont prises en charge dans Windows Workflow Foundation (WF). Les projets de workflow en C# créés dans Visual Studio 2012 qui ciblent .NET Framework 4.5 utilisent les expressions C#, et les projets de workflow en Visual Basic utilisent les expressions Visual Basic. Pour spécifier l’expression C# souhaitée, tapez-la dans la zone intitulée Entrer une expression C#. Cette étiquette s'affiche dans la fenêtre de propriétés lorsque l'activité est sélectionnée dans le concepteur, ou sur l'activité dans Workflow Designer. Dans l'exemple suivant, deux activités WriteLine sont contenues dans Sequence à l'intérieur de NoPersistScope.

Screenshot that shows an automatically created sequence activity.

Remarque

Les expressions C# sont prises en charge uniquement dans Visual Studio et ne sont pas prises en charge dans le concepteur de workflow réhébergé. Pour plus d’informations sur les nouvelles fonctionnalités WF45 prises en charge dans le concepteur réhébergé, consultez Prise en charge des nouvelles fonctionnalités Workflow Foundation 4.5 dans le concepteur de flux de travail réhébergé.

Compatibilité descendante

Les expressions Visual Basic dans les projets de workflow C# .NET Framework 4 existants qui ont été migrés vers .NET Framework 4.6.1 sont prises en charge. Quand les expressions Visual Basic sont consultées dans le concepteur de workflow, le texte de l’expression Visual Basic existante est remplacé par La valeur a été définie en XAML, sauf si l’expression Visual Basic est une syntaxe C# valide. Si l'expression Visual Basic correspond à une syntaxe C# valide, elle s'affiche. Pour mettre à jour les expressions Visual Basic en C#, modifiez-les dans le concepteur de workflow et spécifiez l'expression C# équivalente. Il n'est pas nécessaire de mettre à jour les expressions Visual Basic vers C#, mais une fois les expressions mises à jour dans le concepteur de workflow, elles sont converties en C# et ne peuvent pas être rétablies en Visual Basic.

Utilisation des expressions C# dans les workflows avec code

Les expressions C# sont prises en charge dans les workflows basés sur du code .NET Framework 4.6.1, mais vous devez compiler les expressions C# en utilisant TextExpressionCompiler.Compile pour pouvoir appeler le workflow. Les auteurs de workflow peuvent utiliser CSharpValue comme r-value dans une expression, et CSharpReference comme l-value dans une expression. Dans l'exemple suivant, un workflow qui contient une activité Assign est créé et une activité consistant en une activité WriteLine est contenue dans une activité Sequence. CSharpReference est spécifié pour l’argument To de l’activité Assign, et est utilisé comme l-value de l’expression. CSharpValue est spécifié pour l’argument Value d’Assign, et pour l’argument Text de WriteLine, et est utilisé comme r-value de ces deux expressions.

Variable<int> n = new Variable<int>
{
    Name = "n"
};

Activity wf = new Sequence
{
    Variables = { n },
    Activities =
    {
        new Assign<int>
        {
            To = new CSharpReference<int>("n"),
            Value = new CSharpValue<int>("new Random().Next(1, 101)")
        },
        new WriteLine
        {
            Text = new CSharpValue<string>("\"The number is \" + n")
        }
    }
};

CompileExpressions(wf);

WorkflowInvoker.Invoke(wf);

Une fois que le workflow soit construit, les expressions C# sont compilées en appelant la méthode d'assistance CompileExpressions, puis le workflow. L'exemple suivant utilise la méthode CompileExpressions.

static void CompileExpressions(Activity activity)
{
    // activityName is the Namespace.Type of the activity that contains the
    // C# expressions.
    string activityName = activity.GetType().ToString();

    // Split activityName into Namespace and Type.Append _CompiledExpressionRoot to the type name
    // to represent the new type that represents the compiled expressions.
    // Take everything after the last . for the type name.
    string activityType = activityName.Split('.').Last() + "_CompiledExpressionRoot";
    // Take everything before the last . for the namespace.
    string activityNamespace = string.Join(".", activityName.Split('.').Reverse().Skip(1).Reverse());

    // Create a TextExpressionCompilerSettings.
    TextExpressionCompilerSettings settings = new TextExpressionCompilerSettings
    {
        Activity = activity,
        Language = "C#",
        ActivityName = activityType,
        ActivityNamespace = activityNamespace,
        RootNamespace = null,
        GenerateAsPartialClass = false,
        AlwaysGenerateSource = true,
        ForImplementation = false
    };

    // Compile the C# expression.
    TextExpressionCompilerResults results =
        new TextExpressionCompiler(settings).Compile();

    // Any compilation errors are contained in the CompilerMessages.
    if (results.HasErrors)
    {
        throw new Exception("Compilation failed.");
    }

    // Create an instance of the new compiled expression type.
    ICompiledExpressionRoot compiledExpressionRoot =
        Activator.CreateInstance(results.ResultType,
            new object[] { activity }) as ICompiledExpressionRoot;

    // Attach it to the activity.
    CompiledExpressionInvoker.SetCompiledExpressionRoot(
        activity, compiledExpressionRoot);
}

Notes

Si les expressions C# ne sont pas compilées, une exception NotSupportedException est levée quand le workflow est appelé, avec un message similaire à celui-ci : Expression Activity type 'CSharpValue1’ doit être compilé pour pouvoir s’exécuter. Vérifiez que le workflow a été compilé. »

Si votre workflow basé sur du code personnalisé utilise DynamicActivity, vous devez apporter des modifications à la méthode CompileExpressions, tel que l'indique l'exemple de code suivant.

static void CompileExpressions(DynamicActivity dynamicActivity)
{
    // activityName is the Namespace.Type of the activity that contains the
    // C# expressions. For Dynamic Activities this can be retrieved using the
    // name property , which must be in the form Namespace.Type.
    string activityName = dynamicActivity.Name;

    // Split activityName into Namespace and Type.Append _CompiledExpressionRoot to the type name
    // to represent the new type that represents the compiled expressions.
    // Take everything after the last . for the type name.
    string activityType = activityName.Split('.').Last() + "_CompiledExpressionRoot";
    // Take everything before the last . for the namespace.
    string activityNamespace = string.Join(".", activityName.Split('.').Reverse().Skip(1).Reverse());

    // Create a TextExpressionCompilerSettings.
    TextExpressionCompilerSettings settings = new TextExpressionCompilerSettings
    {
        Activity = dynamicActivity,
        Language = "C#",
        ActivityName = activityType,
        ActivityNamespace = activityNamespace,
        RootNamespace = null,
        GenerateAsPartialClass = false,
        AlwaysGenerateSource = true,
        ForImplementation = true
    };

    // Compile the C# expression.
    TextExpressionCompilerResults results =
        new TextExpressionCompiler(settings).Compile();

    // Any compilation errors are contained in the CompilerMessages.
    if (results.HasErrors)
    {
        throw new Exception("Compilation failed.");
    }

    // Create an instance of the new compiled expression type.
    ICompiledExpressionRoot compiledExpressionRoot =
        Activator.CreateInstance(results.ResultType,
            new object[] { dynamicActivity }) as ICompiledExpressionRoot;

    // Attach it to the activity.
    CompiledExpressionInvoker.SetCompiledExpressionRootForImplementation(
        dynamicActivity, compiledExpressionRoot);
}

Il existe plusieurs différences dans la surcharge de CompileExpressions qui compile les expressions C# dans une activité dynamique.

  • Le paramètre CompileExpressions a la valeur DynamicActivity.

  • Le nom de type et l'espace de noms sont récupérés à l'aide de la propriété DynamicActivity.Name.

  • TextExpressionCompilerSettings.ForImplementation est défini sur true.

  • CompiledExpressionInvoker.SetCompiledExpressionRootForImplementation est appelé au lieu de CompiledExpressionInvoker.SetCompiledExpressionRoot.

Pour plus d’informations sur l’utilisation d’expressions dans le code, consultez Création de workflows, d’activités et d’expressions en utilisant du code impératif.

Utilisation des expressions C# dans les workflows XAML

Les expressions C# sont prises en charge dans les workflows XAML. Les workflows XAML compilés sont compilés en un type, et workflows XAML libre sont chargés par le runtime et compilés dans une arborescence d’activité lorsque le workflow est exécuté.

XAML compilé

Les expressions C# sont prises en charge dans les workflows XAML qui sont compilés dans un type dans le cadre d’un projet de workflow C# qui cible .NET Framework 4.6.1. XAML compilé est le type par défaut de création de workflow dans Visual Studio et les projets de workflow C# créés dans Visual Studio qui ciblent .NET Framework 4.6.1 utilisent les expressions C#.

XAML libre

Les expressions C# sont prises en charge dans les workflows XAML libre. Le programme d’hôte de workflow qui charge et appelle le workflow XAML libre doit cibler .NET Framework 4.6.1, et CompileExpressions doit être défini sur true (la valeur par défaut est false). Pour affecter la valeur CompileExpressions à true, créez une instance ActivityXamlServicesSettings dont la propriété CompileExpressions a la valeur true, et passez-la comme paramètre à ActivityXamlServices.Load. Si CompileExpressions n’est pas défini sur true, une exception NotSupportedException est levée avec un message similaire à celui-ci : Expression Activity type 'CSharpValue1’ doit être compilé pour pouvoir s’exécuter. Vérifiez que le workflow a été compilé. »

ActivityXamlServicesSettings settings = new ActivityXamlServicesSettings
{
    CompileExpressions = true
};

DynamicActivity<int> wf = ActivityXamlServices.Load(new StringReader(serializedAB), settings) as DynamicActivity<int>;

Pour plus d’informations sur l’utilisation de workflows XAML, consultez Sérialisation de workflows et d’activités à partir et à destination du format XAML.

Utilisation des expressions C# dans les services de workflow XAMLX

Les expressions C# sont prises en charge dans les services de workflow XAMLX. Lorsqu'un service de workflow est hébergé dans IIS ou WAS, aucune étape supplémentaire n'est nécessaire, mais si le service de workflow XAML est auto-hébergé, les expressions C# doivent être compilées. Pour compiler les expressions C# dans un service de workflow XAMLX auto-hébergé, chargez d’abord le fichier XAMLX dans un WorkflowService et passez le Body du WorkflowService à la méthode CompileExpressions décrite dans la section précédente Utilisation des expressions C# dans les workflows de code. Dans l'exemple suivant, un service de workflow XAMLX est chargé, les expressions C# sont compilées, puis le service de workflow est ouvert et attend des demandes.

// Load the XAMLX workflow service.
WorkflowService workflow1 =
    (WorkflowService)XamlServices.Load(xamlxPath);

// Compile the C# expressions in the workflow by passing the Body to CompileExpressions.
CompileExpressions(workflow1.Body);

// Initialize the WorkflowServiceHost.
var host = new WorkflowServiceHost(workflow1, new Uri("http://localhost:8293/Service1.xamlx"));

// Enable Metadata publishing/
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);

// Open the WorkflowServiceHost and wait for requests.
host.Open();
Console.WriteLine("Press enter to quit");
Console.ReadLine();

Si les expressions C# ne sont pas compilées, l'opération Open réussit, mais le workflow échoue lorsqu'il est appelé. La méthode CompileExpressions suivante est identique à la méthode de la section précédente Utilisation des expressions C# dans les workflows de code.

static void CompileExpressions(Activity activity)
{
    // activityName is the Namespace.Type of the activity that contains the
    // C# expressions.
    string activityName = activity.GetType().ToString();

    // Split activityName into Namespace and Type.Append _CompiledExpressionRoot to the type name
    // to represent the new type that represents the compiled expressions.
    // Take everything after the last . for the type name.
    string activityType = activityName.Split('.').Last() + "_CompiledExpressionRoot";
    // Take everything before the last . for the namespace.
    string activityNamespace = string.Join(".", activityName.Split('.').Reverse().Skip(1).Reverse());

    // Create a TextExpressionCompilerSettings.
    TextExpressionCompilerSettings settings = new TextExpressionCompilerSettings
    {
        Activity = activity,
        Language = "C#",
        ActivityName = activityType,
        ActivityNamespace = activityNamespace,
        RootNamespace = null,
        GenerateAsPartialClass = false,
        AlwaysGenerateSource = true,
        ForImplementation = false
    };

    // Compile the C# expression.
    TextExpressionCompilerResults results =
        new TextExpressionCompiler(settings).Compile();

    // Any compilation errors are contained in the CompilerMessages.
    if (results.HasErrors)
    {
        throw new Exception("Compilation failed.");
    }

    // Create an instance of the new compiled expression type.
    ICompiledExpressionRoot compiledExpressionRoot =
        Activator.CreateInstance(results.ResultType,
            new object[] { activity }) as ICompiledExpressionRoot;

    // Attach it to the activity.
    CompiledExpressionInvoker.SetCompiledExpressionRoot(
        activity, compiledExpressionRoot);
}