Udostępnij za pośrednictwem


Wyrażenia języka C#

Począwszy od programu .NET Framework 4.5, wyrażenia języka C# są obsługiwane w programie Windows Workflow Foundation (WF). Nowe projekty przepływu pracy języka C# utworzone w programie Visual Studio 2012 przeznaczone dla platformy .NET Framework 4.5 używają wyrażeń języka C#, a projekty przepływu pracy języka Visual Basic używają wyrażeń języka Visual Basic. Istniejące projekty przepływu pracy programu .NET Framework 4 korzystające z wyrażeń języka Visual Basic można migrować do programu .NET Framework 4.6.1 niezależnie od języka projektu i są obsługiwane. Ten temat zawiera omówienie wyrażeń języka C# w programie WF.

Używanie wyrażeń języka C# w przepływach pracy

Używanie wyrażeń języka C# w Projektant przepływu pracy

Począwszy od programu .NET Framework 4.5, wyrażenia języka C# są obsługiwane w programie Windows Workflow Foundation (WF). Projekty przepływu pracy języka C# utworzone w programie Visual Studio 2012 przeznaczone dla platformy .NET Framework 4.5 używają wyrażeń języka C#, podczas gdy projekty przepływu pracy języka Visual Basic używają wyrażeń języka Visual Basic. Aby określić żądane wyrażenie języka C#, wpisz je w polu z etykietą Wprowadź wyrażenie języka C#. Ta etykieta jest wyświetlana w oknie właściwości po wybraniu działania w projektancie lub w działaniu w projektancie przepływu pracy. W poniższym przykładzie dwa WriteLine działania znajdują się wewnątrz Sequence elementu NoPersistScope.

Screenshot that shows an automatically created sequence activity.

Uwaga

Wyrażenia języka C# są obsługiwane tylko w programie Visual Studio i nie są obsługiwane w projektancie ponownie hostowanego przepływu pracy. Aby uzyskać więcej informacji na temat nowych funkcji platformy WF45 obsługiwanych w ponownym projektancie, zobacz Obsługa nowych funkcji programu Workflow Foundation 4.5 w Projektant ponownego hostowanego przepływu pracy.

Zgodność z poprzednimi wersjami

Obsługiwane są wyrażenia języka Visual Basic w istniejących projektach przepływu pracy .NET Framework 4 C#, które zostały zmigrowane do programu .NET Framework 4.6.1. Gdy wyrażenia języka Visual Basic są wyświetlane w projektancie przepływu pracy, tekst istniejącego wyrażenia języka Visual Basic jest zastępowany wartością ustawioną w języku XAML, chyba że wyrażenie języka Visual Basic jest prawidłową składnią języka C#. Jeśli wyrażenie języka Visual Basic jest prawidłową składnią języka C#, zostanie wyświetlone wyrażenie. Aby zaktualizować wyrażenia języka Visual Basic do języka C#, można je edytować w projektancie przepływu pracy i określić równoważne wyrażenie języka C#. Nie jest wymagane zaktualizowanie wyrażeń języka Visual Basic do języka C#, ale po zaktualizowaniu wyrażeń w projektancie przepływu pracy są konwertowane na język C# i mogą nie zostać przywrócone do języka Visual Basic.

Używanie wyrażeń języka C# w przepływach pracy kodu

Wyrażenia języka C# są obsługiwane w przepływach pracy opartych na kodzie programu .NET Framework 4.6.1, ale zanim przepływ pracy będzie można wywołać, należy skompilować wyrażenia języka C# przy użyciu polecenia TextExpressionCompiler.Compile. Autorzy przepływów pracy mogą użyć CSharpValue funkcji do reprezentowania wartości r wyrażenia oraz CSharpReference do reprezentowania wartości l wyrażenia. W poniższym przykładzie przepływ pracy jest tworzony przy użyciu Assign działania i WriteLine działania zawartego Sequence w działaniu. Parametr A CSharpReference jest określony dla To argumentu Assign, i reprezentuje wartość l wyrażenia. Argument a CSharpValue jest określony dla Value argumentu Assign, i dla Text argumentu WriteLine, i reprezentuje wartość r dla tych dwóch wyrażeń.

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

Po utworzeniu przepływu pracy wyrażenia języka C# są kompilowane przez wywołanie metody pomocniczej CompileExpressions , a następnie wywoływanie przepływu pracy. Poniższy przykład to CompileExpressions metoda .

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

Uwaga

Jeśli wyrażenia języka C# nie są kompilowane, NotSupportedException jest zgłaszany, gdy przepływ pracy jest wywoływany z komunikatem podobnym do następującego: Expression Activity type 'CSharpValue1' wymaga kompilacji w celu uruchomienia. Upewnij się, że przepływ pracy został skompilowany".

Jeśli niestandardowy przepływ pracy oparty na kodzie używa DynamicActivitymetody , wymagane są pewne zmiany CompileExpressions w metodzie, jak pokazano w poniższym przykładzie kodu.

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

Istnieje kilka różnic w CompileExpressions przeciążeniu, które kompiluje wyrażenia języka C# w działaniu dynamicznym.

  • Parametr to CompileExpressionsDynamicActivity.

  • Nazwa typu i przestrzeń nazw są pobierane przy użyciu DynamicActivity.Name właściwości .

  • TextExpressionCompilerSettings.ForImplementation jest ustawiona na truewartość .

  • CompiledExpressionInvoker.SetCompiledExpressionRootForImplementation jest wywoływana CompiledExpressionInvoker.SetCompiledExpressionRootzamiast .

Aby uzyskać więcej informacji na temat pracy z wyrażeniami w kodzie, zobacz Tworzenie przepływów pracy, działań i wyrażeń przy użyciu kodu imperatywnego.

Używanie wyrażeń języka C# w przepływach pracy XAML

Wyrażenia języka C# są obsługiwane w przepływach pracy XAML. Skompilowane przepływy pracy XAML są kompilowane w typie, a luźne przepływy pracy XAML są ładowane przez środowisko uruchomieniowe i kompilowane w drzewie działań podczas wykonywania przepływu pracy.

Skompilowany kod Xaml

Wyrażenia języka C# są obsługiwane w skompilowanych przepływach pracy XAML, które są kompilowane do typu w ramach projektu przepływu pracy języka C#, który jest przeznaczony dla programu .NET Framework 4.6.1. Skompilowany kod XAML jest domyślnym typem tworzenia przepływu pracy w programie Visual Studio, a projekty przepływu pracy języka C# utworzone w programie Visual Studio przeznaczone dla platformy .NET Framework 4.6.1 używają wyrażeń języka C#.

Luźne Xaml

Wyrażenia języka C# są obsługiwane w luźnych przepływach pracy XAML. Program hosta przepływu pracy, który ładuje i wywołuje luźny przepływ pracy XAML, musi być przeznaczony dla programu .NET Framework 4.6.1 i CompileExpressions musi być ustawiony na true wartość (wartość domyślna to false). Aby ustawić CompileExpressionstruewartość , utwórz ActivityXamlServicesSettings wystąpienie z właściwością CompileExpressions ustawioną na true, a następnie przekaż je jako parametr do ActivityXamlServices.Load. Jeśli CompileExpressions nie ustawiono truewartości , NotSupportedException zostanie zgłoszony komunikat podobny do następującego: Expression Activity type 'CSharpValue1' wymaga kompilacji w celu uruchomienia. Upewnij się, że przepływ pracy został skompilowany".

ActivityXamlServicesSettings settings = new ActivityXamlServicesSettings
{
    CompileExpressions = true
};

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

Aby uzyskać więcej informacji na temat pracy z przepływami pracy XAML, zobacz Serializowanie przepływów pracy i działań do i z XAML.

Używanie wyrażeń języka C# w usługach przepływu pracy XAMLX

Wyrażenia języka C# są obsługiwane w usługach przepływu pracy XAMLX. Jeśli usługa przepływu pracy jest hostowana w usługach IIS lub WAS, nie są wymagane żadne dodatkowe kroki, ale jeśli usługa przepływu pracy XAML jest hostowana samodzielnie, należy skompilować wyrażenia języka C#. Aby skompilować wyrażenia języka C# w samoobsługowej usłudze przepływu pracy XAMLX, najpierw załaduj plik XAMLX do WorkflowServiceelementu , a następnie przekaż element WorkflowServiceBody do CompileExpressions metody opisanej w poprzedniej sekcji Używanie wyrażeń języka C# w sekcji przepływów pracy kodu. W poniższym przykładzie jest ładowana usługa przepływu pracy XAMLX, skompilowane są wyrażenia języka C#, a następnie usługa przepływu pracy jest otwierana i czeka na żądania.

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

Jeśli wyrażenia języka C# nie zostaną skompilowane, operacja zakończy się pomyślnie, Open ale przepływ pracy zakończy się niepowodzeniem po wywołaniu. Poniższa CompileExpressions metoda jest taka sama jak metoda z poprzedniej sekcji Używanie wyrażeń języka C# w sekcji przepływów pracy kodu.

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