워크플로 및 활동과 XAML 간 직렬화
어셈블리에 포함되어 있는 형식으로 컴파일하는 것 외에 워크플로 정의를 XAML로 serialize할 수도 있습니다. serialize된 이 정의를 다시 로드하여 편집 또는 검사하거나, 빌드 시스템에 전달하여 컴파일하거나, 로드 및 호출할 수 있습니다. 이 항목에서는 워크플로 정의의 serialize와 XAML 워크플로 정의의 사용에 대해 간략하게 설명합니다.
XAML 워크플로 정의 작업
ActivityBuilder 클래스를 사용하여 serialization에 대한 워크플로 정의를 만듭니다. ActivityBuilder를 만드는 방법은 DynamicActivity를 만드는 방법과 매우 비슷합니다. 필요한 모든 인수를 지정하고 동작을 구성하는 활동을 구성합니다. 다음 예제에서는 두 개의 인수를 가져와서 두 인수를 함께 추가하고 결과를 반환하는 Add
활동을 만듭니다. 이 활동은 결과를 반환하므로 제네릭 ActivityBuilder<TResult> 클래스가 사용됩니다.
ActivityBuilder<int> ab = new ActivityBuilder<int>();
ab.Name = "Add";
ab.Properties.Add(new DynamicActivityProperty { Name = "Operand1", Type = typeof(InArgument<int>) });
ab.Properties.Add(new DynamicActivityProperty { Name = "Operand2", Type = typeof(InArgument<int>) });
ab.Implementation = new Sequence
{
Activities =
{
new WriteLine
{
Text = new VisualBasicValue<string>("Operand1.ToString() + \" + \" + Operand2.ToString()")
},
new Assign<int>
{
To = new ArgumentReference<int> { ArgumentName = "Result" },
Value = new VisualBasicValue<int>("Operand1 + Operand2")
}
}
};
각각의 DynamicActivityProperty 인스턴스는 워크플로에 대한 입력 인수 중 하나를 나타내며 Implementation에는 워크플로의 논리를 구성하는 활동이 포함되어 있습니다. 이 예제의 r-value 식은 Visual Basic 식입니다. 람다 식은 Convert를 사용하지 않으면 XAML로 serialize할 수 없습니다. 직렬화된 워크플로를 워크플로 디자이너에서 열거나 편집하려고 할 경우 Visual Basic 식을 사용해야 합니다. 자세한 내용은 명령 코드를 사용하여 워크플로, 활동 및 식 작성을 참조하세요.
ActivityBuilder 인스턴스가 나타내는 워크플로 정의를 XAML로 serialize하려면 ActivityXamlServices를 사용하여 XamlWriter를 만든 다음, XamlServices를 사용하여 XamlWriter를 통해 워크플로 정의를 serialize합니다. ActivityXamlServices에는 ActivityBuilder 인스턴스와 XAML 간을 매핑하고, XAML 워크플로를 로드하고, 호출 가능한 DynamicActivity를 반환하는 메서드가 있습니다. 다음 예제에서는 이전 예제의 ActivityBuilder 인스턴스를 문자열로 직렬화하고 파일로 저장합니다.
// Serialize the workflow to XAML and store it in a string.
StringBuilder sb = new StringBuilder();
StringWriter tw = new StringWriter(sb);
XamlWriter xw = ActivityXamlServices.CreateBuilderWriter(new XamlXmlWriter(tw, new XamlSchemaContext()));
XamlServices.Save(xw, ab);
string serializedAB = sb.ToString();
// Display the XAML to the console.
Console.WriteLine(serializedAB);
// Serialize the workflow to XAML and save it to a file.
StreamWriter sw = File.CreateText(@"C:\Workflows\add.xaml");
XamlWriter xw2 = ActivityXamlServices.CreateBuilderWriter(new XamlXmlWriter(sw, new XamlSchemaContext()));
XamlServices.Save(xw2, ab);
sw.Close();
다음 예제에서는 serialize된 워크플로를 나타냅니다.
<Activity
x:TypeArguments="x:Int32"
x:Class="Add"
xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<x:Members>
<x:Property Name="Operand1" Type="InArgument(x:Int32)" />
<x:Property Name="Operand2" Type="InArgument(x:Int32)" />
</x:Members>
<Sequence>
<WriteLine Text="[Operand1.ToString() + " + " + Operand2.ToString()]" />
<Assign x:TypeArguments="x:Int32" Value="[Operand1 + Operand2]">
<Assign.To>
<OutArgument x:TypeArguments="x:Int32">
<ArgumentReference x:TypeArguments="x:Int32" ArgumentName="Result" />
</OutArgument>
</Assign.To>
</Assign>
</Sequence>
</Activity>
ActivityXamlServices Load 메서드를 사용하여 직렬화된 워크플로를 로드합니다. 이 메서드는 serialize된 워크플로 정의를 사용하고 워크플로 정의를 나타내는 DynamicActivity를 반환합니다. 유효성 검사 프로세스가 진행되는 동안 CacheMetadata의 본문에서 DynamicActivity를 호출할 때까지는 XAML이 역직렬화되지 않습니다. 유효성 검사를 명시적으로 호출하지 않으면 워크플로가 호출될 때 유효성 검사가 수행됩니다. XAML 워크플로 정의가 잘못된 경우 ArgumentException 예외가 throw됩니다. CacheMetadata에서 throw된 예외는 모두 Validate에 대한 호출에서 이스케이프되며 호출자가 처리해야 합니다. 다음 예제에서는 이전 예제에서 serialize된 워크플로를 로드하고 WorkflowInvoker를 사용하여 호출합니다.
// Load the workflow definition from XAML and invoke it.
DynamicActivity<int> wf = ActivityXamlServices.Load(new StringReader(serializedAB)) as DynamicActivity<int>;
Dictionary<string, object> wfParams = new Dictionary<string, object>
{
{ "Operand1", 25 },
{ "Operand2", 15 }
};
int result = WorkflowInvoker.Invoke(wf, wfParams);
Console.WriteLine(result);
이 워크플로가 호출되면 다음 출력이 콘솔에 표시됩니다.
25 + 15
40
참고 항목
입력 및 출력 인수로 워크플로를 호출하는 방법에 대한 자세한 내용은 WorkflowInvoker 및 WorkflowApplication 사용과 Invoke을 참조하세요.
직렬화된 워크플로에 C# 식이 포함된 경우 CompileExpressions 속성이 true
로 설정된 ActivityXamlServicesSettings 인스턴스를 ActivityXamlServices.Load 매개 변수로 전달해야 합니다. 그렇지 않으면 'CSharpValue`1' 식 작업 형식을 실행하려면 컴파일이 필요합니다. 워크플로가 컴파일되었는지 확인하세요.와 유사한 메시지와 함께 NotSupportedException이 발생합니다.
ActivityXamlServicesSettings settings = new ActivityXamlServicesSettings
{
CompileExpressions = true
};
DynamicActivity<int> wf = ActivityXamlServices.Load(new StringReader(serializedAB), settings) as DynamicActivity<int>;
자세한 내용은 C# 식을 참조하세요.
ActivityXamlServices CreateBuilderReader 메서드를 사용하여 직렬화된 워크플로 정의를 ActivityBuilder 인스턴스로 로드할 수도 있습니다. 직렬화된 워크플로를 ActivityBuilder 인스턴스로 로드하면 검사하고 수정할 수 있습니다. 이 방법은 사용자 지정 워크플로 디자이너 작성자에게 유용하며, 디자인 프로세스가 진행되는 동안 워크플로 정의를 저장하고 다시 로드하기 위한 메커니즘을 제공합니다. 다음 예제에서는 이전 예제에서 serialize된 워크플로 정의를 로드하고 해당 속성을 검사합니다.
// Create a new ActivityBuilder and initialize it using the serialized
// workflow definition.
ActivityBuilder<int> ab2 = XamlServices.Load(
ActivityXamlServices.CreateBuilderReader(
new XamlXmlReader(new StringReader(serializedAB)))) as ActivityBuilder<int>;
// Now you can continue working with the ActivityBuilder, inspect
// properties, etc...
Console.WriteLine("There are {0} arguments in the activity builder.", ab2.Properties.Count);
foreach (var prop in ab2.Properties)
{
Console.WriteLine("Name: {0}, Type: {1}", prop.Name, prop.Type);
}
.NET