Delen via


C#-expressies

Vanaf .NET Framework 4.5 worden C#-expressies ondersteund in Windows Workflow Foundation (WF). Nieuwe C#-werkstroomprojecten die zijn gemaakt in Visual Studio 2012 die gericht zijn op .NET Framework 4.5, gebruiken C#-expressies en Visual Basic-werkstroomprojecten maken gebruik van Visual Basic-expressies. Bestaande .NET Framework 4-werkstroomprojecten die gebruikmaken van Visual Basic-expressies kunnen worden gemigreerd naar .NET Framework 4.6.1, ongeacht de projecttaal en worden ondersteund. Dit onderwerp bevat een overzicht van C#-expressies in WF.

C#-expressies gebruiken in werkstromen

C#-expressies gebruiken in workflowontwerper

Vanaf .NET Framework 4.5 worden C#-expressies ondersteund in Windows Workflow Foundation (WF). C#-werkstroomprojecten die zijn gemaakt in Visual Studio 2012 die gericht zijn op .NET Framework 4.5, gebruiken C#-expressies, terwijl Visual Basic-werkstroomprojecten Visual Basic-expressies gebruiken. Als u de gewenste C#-expressie wilt opgeven, typt u deze in het vak met de naam Een C#-expressie invoeren. Dit label wordt weergegeven in het eigenschappenvenster wanneer de activiteit is geselecteerd in de ontwerpfunctie of op de activiteit in de werkstroomontwerper. In het volgende voorbeeld zijn twee WriteLine activiteiten opgenomen in een Sequence binnenkant van een NoPersistScope.

Screenshot that shows an automatically created sequence activity.

Notitie

C#-expressies worden alleen ondersteund in Visual Studio en worden niet ondersteund in de opnieuw gehoste werkstroomontwerper. Zie Support for New Workflow Foundation 4.5 Features in the Rehosted Workflow Designer (Support for New Workflow Foundation 4.5 Features in the Rehosted Workflow Designer) voor meer informatie over nieuwe WF45-functies die worden ondersteund in de opnieuw gehoste ontwerper van werkstromen.

Compatibiliteit met eerdere versies

Visual Basic-expressies in bestaande .NET Framework 4 C#-werkstroomprojecten die zijn gemigreerd naar .NET Framework 4.6.1 worden ondersteund. Wanneer de Visual Basic-expressies worden weergegeven in de werkstroomontwerper, wordt de tekst van de bestaande Visual Basic-expressie vervangen door Waarde die is ingesteld in XAML, tenzij de Visual Basic-expressie geldige C#-syntaxis is. Als de Visual Basic-expressie een geldige C#-syntaxis is, wordt de expressie weergegeven. Als u de Visual Basic-expressies wilt bijwerken naar C#, kunt u deze bewerken in de werkstroomontwerper en de equivalente C#-expressie opgeven. Het is niet vereist om de Visual Basic-expressies bij te werken naar C#, maar zodra de expressies zijn bijgewerkt in de werkstroomontwerper, worden ze geconverteerd naar C# en worden ze mogelijk niet teruggezet naar Visual Basic.

C#-expressies gebruiken in codewerkstromen

C#-expressies worden ondersteund in op code gebaseerde werkstromen van .NET Framework 4.6.1, maar voordat de werkstroom kan worden aangeroepen, moeten de C#-expressies worden gecompileerd met behulp van TextExpressionCompiler.Compile. Werkstroomauteurs kunnen de CSharpValue r-waarde van een expressie vertegenwoordigen en CSharpReference de l-waarde van een expressie vertegenwoordigen. In het volgende voorbeeld wordt een werkstroom gemaakt met een Assign activiteit en een WriteLine activiteit in een Sequence activiteit. Er wordt een CSharpReference opgegeven voor het argument van de To Assign, en vertegenwoordigt de l-waarde van de expressie. Er wordt een CSharpValue opgegeven voor het argument van de Value Assign, en voor het argument van de Text WriteLine, en vertegenwoordigt de r-waarde voor deze twee expressies.

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);

Nadat de werkstroom is samengesteld, worden de C#-expressies gecompileerd door de CompileExpressions helpermethode aan te roepen en vervolgens wordt de werkstroom aangeroepen. Het volgende voorbeeld is de CompileExpressions methode.

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);
}

Notitie

Als de C#-expressies niet zijn gecompileerd, wordt er een NotSupportedException gegenereerd wanneer de werkstroom wordt aangeroepen met een bericht dat vergelijkbaar is met het volgende: Expression Activity type 'CSharpValue1 vereist compilatie om uit te voeren. Zorg ervoor dat de werkstroom is gecompileerd.'

Als uw aangepaste werkstroom op basis van code wordt gebruikt DynamicActivity, zijn er enkele wijzigingen in de CompileExpressions methode vereist, zoals wordt weergegeven in het volgende codevoorbeeld.

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);
}

Er zijn verschillende verschillen in de CompileExpressions overbelasting waarmee de C#-expressies in een dynamische activiteit worden gecompileerd.

  • De parameter die moet worden gebruikt CompileExpressions , is een DynamicActivity.

  • De typenaam en naamruimte worden opgehaald met behulp van de DynamicActivity.Name eigenschap.

  • TextExpressionCompilerSettings.ForImplementation is ingesteld op true.

  • CompiledExpressionInvoker.SetCompiledExpressionRootForImplementation wordt aangeroepen in plaats van CompiledExpressionInvoker.SetCompiledExpressionRoot.

Zie Werkstromen, activiteiten en expressies ontwerpen met imperatieve code voor meer informatie over het werken met expressies in code.

C#-expressies gebruiken in XAML-werkstromen

C#-expressies worden ondersteund in XAML-werkstromen. Gecompileerde XAML-werkstromen worden gecompileerd in een type en losse XAML-werkstromen worden geladen door de runtime en gecompileerd in een activiteitenstructuur wanneer de werkstroom wordt uitgevoerd.

Gecompileerd Xaml

C#-expressies worden ondersteund in gecompileerde XAML-werkstromen die zijn gecompileerd naar een type als onderdeel van een C#-werkstroomproject dat is gericht op .NET Framework 4.6.1. Gecompileerde XAML is het standaardtype werkstroomcreatie in Visual Studio en C#-werkstroomprojecten die zijn gemaakt in Visual Studio die gericht zijn op .NET Framework 4.6.1, gebruiken C#-expressies.

Losse Xaml

C#-expressies worden ondersteund in losse XAML-werkstromen. Het werkstroomhostprogramma dat de losse XAML-werkstroom laadt en aanroept, moet zijn gericht op .NET Framework 4.6.1 en CompileExpressions moet worden ingesteld true op (de standaardinstelling is false). Als u wilt trueinstellenCompileExpressions, maakt u een ActivityXamlServicesSettings exemplaar waarop de eigenschap is CompileExpressions ingesteld trueen geeft u het door als parameter aan ActivityXamlServices.Load. Als CompileExpressions dit niet is ingesteld trueop, wordt er een NotSupportedException bericht gegenereerd dat lijkt op het volgende: Expression Activity type 'CSharpValue1 vereist compilatie om uit te voeren. Zorg ervoor dat de werkstroom is gecompileerd.'

ActivityXamlServicesSettings settings = new ActivityXamlServicesSettings
{
    CompileExpressions = true
};

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

Zie Werkstromen en activiteiten van en naar XAML serialiseren voor meer informatie over het werken met XAML-werkstromen.

C#-expressies gebruiken in XAMLX-werkstroomservices

C#-expressies worden ondersteund in XAMLX-werkstroomservices. Wanneer een werkstroomservice wordt gehost in IIS of WAS, zijn er geen extra stappen vereist, maar als de XAML-werkstroomservice zelf wordt gehost, moeten de C#-expressies worden gecompileerd. Als u de C#-expressies wilt compileren in een zelf-hostende XAMLX-werkstroomservice, laadt u eerst het XAMLX-bestand in een WorkflowServiceen geeft u de Body van de WorkflowService expressie door aan de CompileExpressions methode die wordt beschreven in de vorige sectie C#-expressies in codewerkstromen . In het volgende voorbeeld wordt een XAMLX-werkstroomservice geladen, worden de C#-expressies gecompileerd en wordt de werkstroomservice geopend en wordt gewacht op aanvragen.

// 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();

Als de C#-expressies niet zijn gecompileerd, slaagt de bewerking, maar mislukt de Open werkstroom wanneer deze wordt aangeroepen. De volgende CompileExpressions methode is hetzelfde als de methode uit de vorige sectie C#-expressies gebruiken in de sectie codewerkstromen .

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);
}