Dela via


C#-uttryck

Från och med .NET Framework 4.5 stöds C#-uttryck i Windows Workflow Foundation (WF). Nya C#-arbetsflödesprojekt som skapats i Visual Studio 2012 och som är mål för .NET Framework 4.5 använder C#-uttryck och Visual Basic-arbetsflödesprojekt använder Visual Basic-uttryck. Befintliga .NET Framework 4-arbetsflödesprojekt som använder Visual Basic-uttryck kan migreras till .NET Framework 4.6.1 oavsett projektspråk och stöds. Det här avsnittet innehåller en översikt över C#-uttryck i WF.

Använda C#-uttryck i arbetsflöden

Använda C#-uttryck i arbetsflödesdesignern

Från och med .NET Framework 4.5 stöds C#-uttryck i Windows Workflow Foundation (WF). C#-arbetsflödesprojekt som skapats i Visual Studio 2012 och som riktar sig mot .NET Framework 4.5 använder C#-uttryck, medan Visual Basic-arbetsflödesprojekt använder Visual Basic-uttryck. Om du vill ange önskat C#-uttryck skriver du det i rutan med etiketten Ange ett C#-uttryck. Den här etiketten visas i egenskapsfönstret när aktiviteten väljs i designern eller på aktiviteten i arbetsflödesdesignern. I följande exempel finns två WriteLine aktiviteter i en Sequence i en NoPersistScope.

Screenshot that shows an automatically created sequence activity.

Kommentar

C#-uttryck stöds endast i Visual Studio och stöds inte i den nya arbetsflödesdesignern. Mer information om nya WF45-funktioner som stöds i den omvärdade designern finns i Stöd för nya Workflow Foundation 4.5-funktioner i arbetsflödesdesignern med nytt värd.

Bakåtkompatibilitet

Visual Basic-uttryck i befintliga .NET Framework 4 C#-arbetsflödesprojekt som har migrerats till .NET Framework 4.6.1 stöds. När Visual Basic-uttrycken visas i arbetsflödesdesignern ersätts texten i det befintliga Visual Basic-uttrycket med Värde i XAML, såvida inte Visual Basic-uttrycket är giltig C#-syntax. Om Visual Basic-uttrycket är giltig C#-syntax visas uttrycket. Om du vill uppdatera Visual Basic-uttrycken till C# kan du redigera dem i arbetsflödesdesignern och ange motsvarande C#-uttryck. Det krävs inte att du uppdaterar Visual Basic-uttrycken till C#, men när uttrycken har uppdaterats i arbetsflödesdesignern konverteras de till C# och kan inte återställas till Visual Basic.

Använda C#-uttryck i kodarbetsflöden

C#-uttryck stöds i .NET Framework 4.6.1-kodbaserade arbetsflöden, men innan arbetsflödet kan anropas måste C#-uttrycken kompileras med .TextExpressionCompiler.Compile Arbetsflödesförfattare kan använda CSharpValue för att representera r-värdet för ett uttryck och CSharpReference för att representera l-värdet för ett uttryck. I följande exempel skapas ett arbetsflöde med en Assign aktivitet och en WriteLine aktivitet som ingår i en Sequence aktivitet. A CSharpReference anges för To argumentet Assigni och representerar uttryckets l-värde. A CSharpValue anges för Value argumentet Assignför , och för argumentet WriteLineför Text , och representerar r-värdet för dessa två uttryck.

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

När arbetsflödet har konstruerats kompileras C#-uttrycken CompileExpressions genom att anropa hjälpmetoden och sedan anropas arbetsflödet. Följande exempel är CompileExpressions metoden.

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

Kommentar

Om C#-uttrycken inte kompileras utlöses ett NotSupportedException när arbetsflödet anropas med ett meddelande som liknar följande: Expression Activity type 'CSharpValue1' kräver kompilering för att kunna köras. Kontrollera att arbetsflödet har kompilerats."

Om ditt anpassade kodbaserade arbetsflöde använder DynamicActivitykrävs vissa ändringar av CompileExpressions metoden, vilket visas i följande kodexempel.

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

Det finns flera skillnader i överbelastningen CompileExpressions som kompilerar C#-uttrycken i en dynamisk aktivitet.

  • Parametern till CompileExpressions är en DynamicActivity.

  • Typnamnet och namnområdet hämtas med hjälp av DynamicActivity.Name egenskapen .

  • TextExpressionCompilerSettings.ForImplementation är inställt på true.

  • CompiledExpressionInvoker.SetCompiledExpressionRootForImplementation anropas i stället CompiledExpressionInvoker.SetCompiledExpressionRootför .

Mer information om hur du arbetar med uttryck i kod finns i Redigera arbetsflöden, aktiviteter och uttryck med imperativ kod.

Använda C#-uttryck i XAML-arbetsflöden

C#-uttryck stöds i XAML-arbetsflöden. Kompilerade XAML-arbetsflöden kompileras till en typ och lösa XAML-arbetsflöden läses in av körningen och kompileras till ett aktivitetsträd när arbetsflödet körs.

Kompilerad Xaml

C#-uttryck stöds i kompilerade XAML-arbetsflöden som kompileras till en typ som en del av ett C#-arbetsflödesprojekt som riktar sig till .NET Framework 4.6.1. Kompilerad XAML är standardtypen för arbetsflödesredigering i Visual Studio, och C#-arbetsflödesprojekt som skapats i Visual Studio som är mål för .NET Framework 4.6.1 använder C#-uttryck.

Lös Xaml

C#-uttryck stöds i lösa XAML-arbetsflöden. Arbetsflödets värdprogram som läser in och anropar det lösa XAML-arbetsflödet måste ha .NET Framework 4.6.1 som mål och CompileExpressions måste anges till true (standardvärdet är false). Om du vill ange CompileExpressions till trueskapar du en ActivityXamlServicesSettings instans med dess CompileExpressions egenskap inställd på trueoch skickar den som en parameter till ActivityXamlServices.Load. Om CompileExpressions Är inte inställt på truegenereras ett NotSupportedException med ett meddelande som liknar följande: Expression Activity type 'CSharpValue1' kräver kompilering för att kunna köras. Kontrollera att arbetsflödet har kompilerats."

ActivityXamlServicesSettings settings = new ActivityXamlServicesSettings
{
    CompileExpressions = true
};

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

Mer information om hur du arbetar med XAML-arbetsflöden finns i Serialisera arbetsflöden och aktiviteter till och från XAML.

Använda C#-uttryck i XAMLX-arbetsflödestjänster

C#-uttryck stöds i XAMLX-arbetsflödestjänster. När en arbetsflödestjänst finns i IIS eller WAS krävs inga ytterligare steg, men om XAML-arbetsflödestjänsten är lokalt installerad måste C#-uttrycken kompileras. Om du vill kompilera C#-uttrycken i en XAMLX-arbetsflödestjänst med egen värd läser du först in XAMLX-filen i en WorkflowServiceoch skickar Body sedan till WorkflowService metoden CompileExpressions som beskrivs i föregående avsnitt Använda C#-uttryck i kodarbetsflöden . I följande exempel läses en XAMLX-arbetsflödestjänst in, C#-uttryck kompileras och sedan öppnas arbetsflödestjänsten och väntar på begäranden.

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

Om C#-uttrycken inte kompileras lyckas åtgärden, Open men arbetsflödet misslyckas när det anropas. Följande CompileExpressions metod är samma som metoden från föregående avsnitt Använda C#-uttryck i kodarbetsflöden .

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