C# の式
.NET Framework 4.5 以降では、Windows Workflow Foundation (WF) で C# 式がサポートされています。 Visual Studio 2012 で作成された、.NET Framework 4.5 を対象とする新しい 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# 式がサポートされています。 Visual Studio 2012 で作成された、.NET Framework 4.5 を対象とする C# ワークフロー プロジェクトでは C# 式が使用され、Visual Basic ワークフロー プロジェクトでは Visual Basic 式が使用されます。 必要な C# 式を指定するには、 [C# の式を入力してください] というラベルの付いたボックスにそれを入力します。 このラベルは、プロパティ ウィンドウ (デザイナーでアクティビティを選択した場合) またはワークフロー デザイナーのアクティビティに表示されます。 次の例では、2 つの WriteLine
アクティビティが Sequence
の中で NoPersistScope
内に含まれています。
Note
C# 式は、Visual Studio でのみサポートされており、再ホストされたワークフロー デザイナーではサポートされていません。 再ホストされたデザイナーでサポートされている WF45 の新機能の詳細については、「再ホストされたワークフロー デザイナーにおける Workflow Foundation 4.5 の新機能のサポート」を参照してください。
下位互換性
.NET Framework 4.6.1 に移行した .NET Framework 4 の既存の C# ワークフロー プロジェクトに含まれる Visual Basic 式はサポートされています。 Visual Basic 式をワークフロー デザイナーで表示すると、既存の Visual Basic 式のテキストは、その Visual Basic 式が有効な C# 構文である場合を除き、"値が 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
を使用して式の右辺値を表し、CSharpReference
を使用して式の左辺値を表すことができます。 次の例では、Assign
アクティビティに含まれる WriteLine
アクティビティと Sequence
アクティビティを使用してワークフローを作成します。 CSharpReference
は Assign
の To
引数として指定され、式の左辺値を表します。 CSharpValue
は Assign
の Value
引数、および WriteLine
の Text
引数として指定され、2 つの式の右辺値を表します。
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 'CSharpValue
1' を実行するにはコンパイルが必要です。 ワークフローがコンパイルされていることを確認してください。"
カスタムのコードベースのワークフローで 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.ForImplementation
はtrue
に設定されます。CompiledExpressionInvoker.SetCompiledExpressionRootForImplementation
の代わりにCompiledExpressionInvoker.SetCompiledExpressionRoot
が呼び出されます。
コード内で式を使用する方法の詳細については、「命令型コードを使用してワークフロー、アクティビティ、および式を作成する方法」を参照してください。
XAML ワークフローでの C# 式の使用
C# 式は XAML ワークフローでサポートされています。 コンパイルされた XAML ワークフローは型にコンパイルされ、Loose XAML ワークフローはランタイムによって読み込まれ、ワークフローの実行時にアクティビティ ツリーにコンパイルされます。
コンパイルされた Xaml
C# 式は、コンパイルされた XAML ワークフローでサポートされており、.NET Framework 4.6.1 を対象とする C# ワークフロー プロジェクトの一部として型にコンパイルされます。 コンパイルされた XAML は Visual Studio でワークフローを作成する場合の既定の種類であり、Visual Studio で作成された、.NET Framework 4.6.1 を対象とする C# ワークフロー プロジェクトでは C# 式が使用されます。
Loose Xaml
C# 式は Loose XAML ワークフローでがサポートされています。 Loose XAML ワークフローを読み込んで呼び出すワークフロー ホスト プログラムは、.NET Framework 4.6.1 を対象としている必要があります。また、CompileExpressions は true
(既定値は false
) に設定する必要があります。 CompileExpressions を true
に設定するには、ActivityXamlServicesSettings プロパティが CompileExpressions に設定されている true
インスタンスを作成し、そのインスタンスを ActivityXamlServices.Load へパラメーターとして渡します。 CompileExpressions
が true
に設定されていない場合は、NotSupportedException がスローされ、以下のようなメッセージが表示されます。"Expression Activity type 'CSharpValue
1' を実行するには、コンパイルが必要です。 ワークフローがコンパイルされていることを確認してください。"
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# 式をコンパイルする必要があります。 C# 式を自己ホスト型の XAMLX ワークフロー サービスでコンパイルするには、最初に XAMLX ファイルを WorkflowService
に読み込んでから、前の「コード ワークフローでの C# 式の使用」で説明した CompileExpressions
メソッドに WorkflowService
の Body
を渡します。 次の例では、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);
}
.NET