次の方法で共有


C# 式

.NET Framework 4.5 以降、Windows Workflow Foundation (WF) では C# 式がサポートされています。 .NET Framework 4.5 を対象とする Visual Studio 2012 で作成された新しい C# ワークフロー プロジェクトは C# 式を使用し、Visual Basic ワークフロー プロジェクトでは Visual Basic 式を使用します。 Visual Basic 式を使用する既存の .NET Framework 4 ワークフロー プロジェクトは、プロジェクト言語に関係なく .NET Framework 4.6.1 に移行でき、サポートされています。 このトピックでは、WF での C# 式の概要について説明します。

ワークフローでの C# 式の使用

ワークフロー デザイナーでの C# 式の使用

.NET Framework 4.5 以降、Windows Workflow Foundation (WF) では C# 式がサポートされています。 .NET Framework 4.5 を対象とする Visual Studio 2012 で作成された C# ワークフロー プロジェクトでは C# 式が使用され、Visual Basic ワークフロー プロジェクトでは Visual Basic 式が使用されます。 目的の C# 式を指定するには、[ Enter a C# expression]\(C# 式を入力する\) というラベルのボックスに入力します。 このラベルは、デザイナーでアクティビティが選択されている場合、またはワークフロー デザイナーのアクティビティでプロパティ ウィンドウに表示されます。 次の例では、2 つのWriteLine アクティビティが、NoPersistScope内のSequence内に含まれています。

自動的に作成されたシーケンス アクティビティを示すスクリーンショット。

C# 式は Visual Studio でのみサポートされ、再ホストされたワークフロー デザイナーではサポートされません。 再ホストされたデザイナーでサポートされる新しい WF45 機能の詳細については、「 再ホストされたワークフロー デザイナーでの新しい Workflow Foundation 4.5 機能のサポート」を参照してください。

下位互換性

.NET Framework 4.6.1 に移行された既存の .NET Framework 4 C# ワークフロー プロジェクトの Visual Basic 式がサポートされています。 Visual Basic 式がワークフロー デザイナーで表示されると、Visual Basic 式が有効な C# 構文でない限り、既存の Visual Basic 式のテキストが XAML で設定された値に置き換えられます。 Visual Basic 式が有効な C# 構文である場合は、式が表示されます。 Visual Basic 式を C# に更新するには、ワークフロー デザイナーでそれらを編集し、同等の C# 式を指定します。 Visual Basic 式を C# に更新する必要はありませんが、ワークフロー デザイナーで式が更新されると、C# に変換され、Visual Basic に戻さない場合があります。

コード ワークフローでの C# 式の使用

C# 式は .NET Framework 4.6.1 コード ベースのワークフローでサポートされていますが、ワークフローを呼び出す前に、 TextExpressionCompiler.Compileを使用して C# 式をコンパイルする必要があります。 ワークフロー作成者は、 CSharpValue を使用して式の r 値を表し、 CSharpReference を使用して式の l 値を表すことができます。 次の例では、Assign アクティビティと、Sequence アクティビティに含まれるWriteLine アクティビティを使用してワークフローを作成します。 CSharpReferenceは、AssignTo引数に指定され、式の l 値を表します。 CSharpValueは、AssignValue引数と、WriteLineText引数に指定され、これら 2 つの式の r 値を表します。

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

ワークフローが構築されると、 CompileExpressions ヘルパー メソッドを呼び出して C# 式がコンパイルされ、ワークフローが呼び出されます。 次の例は、 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);
}

C# 式がコンパイルされていない場合は、次のようなメッセージでワークフローが呼び出されたときに NotSupportedException がスローされます。 Expression Activity type 'CSharpValue1' を実行するにはコンパイルが必要です。 ワークフローがコンパイルされていることを確認してください。

カスタム コード ベースのワークフローで DynamicActivityを使用する場合は、次のコード例に示すように、 CompileExpressions メソッドにいくつかの変更が必要です。

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

動的アクティビティで C# 式をコンパイルする CompileExpressions オーバーロードには、いくつかの違いがあります。

  • CompileExpressionsするパラメーターはDynamicActivityです。

  • 型名と名前空間は、 DynamicActivity.Name プロパティを使用して取得されます。

  • TextExpressionCompilerSettings.ForImplementationtrue に設定されます。

  • CompiledExpressionInvoker.SetCompiledExpressionRootForImplementation は、 CompiledExpressionInvoker.SetCompiledExpressionRootの代わりに呼び出されます。

コードで式を操作する方法の詳細については、「 命令型コードを使用したワークフロー、アクティビティ、および式の作成」を参照してください。

XAML ワークフローでの C# 式の使用

C# 式は XAML ワークフローでサポートされています。 コンパイル済みの XAML ワークフローは型にコンパイルされ、ルーズ XAML ワークフローはランタイムによって読み込まれ、ワークフローの実行時にアクティビティ ツリーにコンパイルされます。

コンパイル済み Xaml

C# 式は、.NET Framework 4.6.1 を対象とする C# ワークフロー プロジェクトの一部として型にコンパイルされるコンパイル済み XAML ワークフローでサポートされます。 コンパイル済み XAML は Visual Studio でのワークフロー作成の既定の種類であり、.NET Framework 4.6.1 を対象とする Visual Studio で作成された C# ワークフロー プロジェクトでは C# 式が使用されます。

Loose Xaml

C# 式は、緩やかな XAML ワークフローでサポートされています。 緩やかな XAML ワークフローを読み込んで呼び出すワークフロー ホスト プログラムは、.NET Framework 4.6.1 を対象とし、 CompileExpressionstrue に設定する必要があります (既定値は false)。 CompileExpressionstrueに設定するには、CompileExpressions プロパティを true に設定してActivityXamlServicesSettings インスタンスを作成し、ActivityXamlServices.Loadするパラメーターとして渡します。 CompileExpressions Is not set to true, a NotSupportedException will be thrown with a message with the following: Expression Activity type 'CSharpValue1' requires compilation to run. ワークフローがコンパイルされていることを確認してください。

ActivityXamlServicesSettings settings = new ActivityXamlServicesSettings
{
    CompileExpressions = true
};

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

XAML ワークフローの操作の詳細については、「XAML との間での ワークフローとアクティビティのシリアル化」を参照してください。

XAMLX ワークフロー サービスでの C# 式の使用

C# 式は、XAMLX ワークフロー サービスでサポートされています。 ワークフロー サービスが IIS または WAS でホストされている場合、追加の手順は必要ありませんが、XAML ワークフロー サービスがセルフホステッドの場合は、C# 式をコンパイルする必要があります。 セルフホステッド XAMLX ワークフロー サービスで C# 式をコンパイルするには、まず XAMLX ファイルをWorkflowServiceに読み込み、次にコード ワークフローの前の「C# 式を使用する」セクションで説明したCompileExpressions メソッドにWorkflowServiceBodyを渡します。 次の例では、XAMLX ワークフロー サービスが読み込まれ、C# 式がコンパイルされ、ワークフロー サービスが開き、要求が待機されます。

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

C# 式がコンパイルされていない場合、 Open 操作は成功しますが、呼び出されるとワークフローは失敗します。 次の CompileExpressions メソッドは、 前のコード ワークフローでの C# 式の使用に関するセクションの メソッドと同じです。

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