Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
Начиная с .NET Framework 4.5 выражения C# поддерживаются в Windows Workflow Foundation (WF). Новые проекты рабочих процессов C#, созданные в Visual Studio 2012, предназначенные для .NET Framework 4.5, используют выражения C# и проекты рабочих процессов Visual Basic используют выражения Visual Basic. Существующие проекты рабочих процессов .NET Framework 4, использующие выражения Visual Basic, можно перенести в .NET Framework 4.6.1 независимо от языка проекта и поддерживаются. В этом разделе представлен обзор выражений C# в WF.
Использование выражений C# в рабочих процессах
Использование выражений C# в конструкторе рабочих процессов
Начиная с .NET Framework 4.5 выражения C# поддерживаются в Windows Workflow Foundation (WF). Проекты рабочих процессов C#, созданные в Visual Studio 2012, предназначенные для .NET Framework 4.5, используют выражения C#, а проекты рабочих процессов Visual Basic используют выражения Visual Basic. Чтобы указать требуемое выражение C#, введите его в поле с меткой ВВОД выражения C#. Эта метка отображается в окне свойств, когда действие выбрано в конструкторе, или на действии в конструкторе рабочих процессов. В следующем примере два WriteLine действия содержатся внутри Sequence и NoPersistScope.
Замечание
Выражения C# поддерживаются только в Visual Studio и не поддерживаются в повторно размещенном конструкторе рабочих процессов. Дополнительные сведения о новых функциях WF45, поддерживаемых в повторно размещенном конструкторе, см. в разделе "Поддержка новых функций Workflow Foundation 4.5" в конструкторе повторно размещенных рабочих процессов.
Обратная совместимость
Поддерживаются выражения Visual Basic в существующих проектах рабочих процессов .NET Framework 4 C#, перенесенных в .NET Framework 4.6.1. При просмотре выражений Visual Basic в конструкторе рабочих процессов текст существующего выражения Visual Basic заменяется на Значение задано в XAML, если выражение Visual Basic не соответствует допустимому синтаксису C#. Если выражение Visual Basic является допустимым синтаксисом C#, отображается выражение. Чтобы обновить выражения Visual Basic на C#, их можно изменить в конструкторе рабочих процессов и указать эквивалентное выражение C#. Для обновления выражений Visual Basic до C# не требуется, но после обновления выражений в конструкторе рабочих процессов они преобразуются в C# и не могут быть возвращены в Visual Basic.
Использование выражений C# в рабочих процессах кода
Выражения C# поддерживаются в рабочих процессах на основе кода .NET Framework 4.6.1, но перед вызовом рабочего процесса выражения C# необходимо скомпилировать с помощью TextExpressionCompiler.Compile. Авторы рабочих процессов могут использовать CSharpValue для представления r-значения выражения и CSharpReference представления l-значения выражения. В следующем примере создается рабочий процесс с действием Assign, а действие WriteLine содержится в действии Sequence. Указан CSharpReference для аргумента To в Assign, и он представляет l-значение выражения. Для CSharpValue аргумента Value и для Assign аргумента Text указано значение WriteLine, которое представляет 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);
После создания рабочего процесса выражения C# компилируются путем вызова вспомогательного CompileExpressions метода, а затем вызывается рабочий процесс. В следующем примере используется 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);
}
Существует несколько различий в перегрузке CompileExpressions , которая компилирует выражения C# в динамическом действии.
Параметр для
CompileExpressionsявляетсяDynamicActivity.Имя типа и пространство имен извлекаются с помощью
DynamicActivity.Nameсвойства.TextExpressionCompilerSettings.ForImplementationзадан какtrue.CompiledExpressionInvoker.SetCompiledExpressionRootForImplementationвызывается вместоCompiledExpressionInvoker.SetCompiledExpressionRoot.
Дополнительные сведения о работе с выражениями в коде см. в статье "Создание рабочих процессов, действий и выражений с помощью императивного кода".
Использование выражений C# в рабочих процессах XAML
Выражения C# поддерживаются в рабочих процессах XAML. Скомпилированные рабочие процессы XAML компилируются в тип, и свободные рабочие процессы XAML загружаются средой выполнения и компилируются в дерево действий при выполнении рабочего процесса.
Скомпилированный Xaml
Выражения C# поддерживаются в скомпилированных рабочих процессах XAML, скомпилированных в тип в рамках проекта рабочего процесса C#, предназначенного для .NET Framework 4.6.1. Скомпилированный XAML — это тип разработки рабочих процессов по умолчанию в Visual Studio, а проекты рабочих процессов C#, созданные в Visual Studio, предназначенные для .NET Framework 4.6.1, используют выражения C#.
Динамический XAML
Выражения C# поддерживаются в свободных рабочих процессах XAML. Программа хоста рабочего процесса, загружающая и вызывающая свободный рабочий процесс XAML, должна быть нацелена на .NET Framework 4.6.1, и CompileExpressions должно быть установлено в true (по умолчанию false). Чтобы задать CompileExpressions на true, создайте экземпляр ActivityXamlServicesSettings с установленным свойством CompileExpressions на true и передайте его в качестве параметра ActivityXamlServices.Load. Если CompileExpressions не установлено в true, будет выброшен NotSupportedException с сообщением, аналогичным следующему: Expression Activity type 'CSharpValue1' требует компиляции для выполнения. Убедитесь, что рабочий процесс скомпилирован.
ActivityXamlServicesSettings settings = new ActivityXamlServicesSettings
{
CompileExpressions = true
};
DynamicActivity<int> wf = ActivityXamlServices.Load(new StringReader(serializedAB), settings) as DynamicActivity<int>;
Дополнительные сведения о работе с рабочими процессами XAML см. в статье сериализация рабочих процессов и действий в XAML и из нее.
Использование выражений C# в службах рабочих процессов XAMLX
Выражения C# поддерживаются в службах рабочих процессов XAMLX. Если служба рабочего процесса размещена в службах IIS или WAS, то никаких дополнительных шагов не требуется, но если служба рабочего процесса XAML размещена самостоятельно, необходимо скомпилировать выражения C#. Чтобы скомпилировать выражения C# в автономной службе рабочих процессов XAMLX, сначала загрузите XAMLX-файл в WorkflowService, а затем передайте метод Body в WorkflowServiceCompileExpressions, описанный в предыдущем разделе "Использование выражений C# в рабочих процессах кода". В следующем примере загружается служба рабочего процесса 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);
}