Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
A partir de .NET Framework 4.5, las expresiones de C# se admiten en Windows Workflow Foundation (WF). Los nuevos proyectos de flujo de trabajo de C# creados en Visual Studio 2012 que tienen como destino .NET Framework 4.5 usan expresiones de C# y los proyectos de flujo de trabajo de Visual Basic usan expresiones de Visual Basic. Los proyectos de flujo de trabajo de .NET Framework 4 existentes que usan expresiones de Visual Basic se pueden migrar a .NET Framework 4.6.1 independientemente del lenguaje del proyecto y sean compatibles. En este tema se proporciona información general sobre las expresiones de C# en WF.
Uso de expresiones de C# en flujos de trabajo
Uso de expresiones de C# en el Diseñador de flujos de trabajo
Uso de expresiones de C# en servicios de flujo de trabajo XAMLX
Uso de expresiones de C# en el Diseñador de flujos de trabajo
A partir de .NET Framework 4.5, las expresiones de C# se admiten en Windows Workflow Foundation (WF). Los proyectos de flujo de trabajo de C# creados en Visual Studio 2012 que tienen como destino .NET Framework 4.5 usan expresiones de C#, mientras que los proyectos de flujo de trabajo de Visual Basic usan expresiones de Visual Basic. Para especificar la expresión de C# deseada, escríbala en el cuadro con la etiqueta Entrar en una expresión de C#. Esta etiqueta se muestra en la ventana de propiedades cuando se selecciona la actividad en el diseñador o en la actividad del diseñador de flujo de trabajo. En el ejemplo siguiente, dos actividades WriteLine
están contenidas dentro de un Sequence
dentro de un NoPersistScope
.
Nota:
Las expresiones de C# solo se admiten en Visual Studio y no se admiten en el diseñador de flujos de trabajo rehospedado. Para obtener más información sobre las nuevas características de WF45 admitidas en el diseñador rehospedado, consulte Compatibilidad con nuevas características de Workflow Foundation 4.5 en el Diseñador de flujos de trabajo rehospedado.
Compatibilidad retroactiva
Se admiten expresiones de Visual Basic en proyectos de flujo de trabajo de C# de .NET Framework 4.6.1 existentes que se han migrado a .NET Framework 4.6.1. Cuando las expresiones de Visual Basic se visualizan en el diseñador de flujo de trabajo, el texto de la expresión existente se reemplaza por El valor se estableció en XAML, a menos que la expresión de Visual Basic sea una sintaxis válida de C#. Si la expresión de Visual Basic es sintaxis de C# válida, se muestra la expresión. Para actualizar las expresiones de Visual Basic a C#, puede editarlas en el diseñador de flujo de trabajo y especificar la expresión de C# equivalente. No es necesario actualizar las expresiones de Visual Basic a C#, pero una vez que las expresiones se actualizan en el diseñador de flujo de trabajo, se convierten en C# y es posible que no se reviertan a Visual Basic.
Uso de expresiones de C# en flujos de trabajo de código
Las expresiones de C# se admiten en flujos de trabajo basados en código de .NET Framework 4.6.1, pero antes de que se pueda invocar el flujo de trabajo, las expresiones de C# deben compilarse mediante TextExpressionCompiler.Compile. Los autores de flujos de trabajo pueden usar CSharpValue
para representar el valor r de una expresión y CSharpReference
para representar el valor l de una expresión. En el ejemplo siguiente, se crea un flujo de trabajo con una Assign
actividad y una WriteLine
actividad contenida en una Sequence
actividad. CSharpReference
Se especifica para el To
argumento de Assign
y representa el valor l de la expresión. CSharpValue
Se especifica para el Value
argumento de Assign
, y para el Text
argumento de WriteLine
, y representa el valor r para esas dos expresiones.
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);
Una vez construido el flujo de trabajo, las expresiones de C# se compilan llamando al CompileExpressions
método auxiliar y, a continuación, se invoca el flujo de trabajo. El ejemplo siguiente es el CompileExpressions
método .
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);
}
Nota:
Si las expresiones de C# no se compilan, se produce una excepción NotSupportedException al invocar el flujo de trabajo con un mensaje similar al siguiente: Expression Activity type 'CSharpValue
1" requiere compilación para ejecutarse. Asegúrese de que se ha compilado el flujo de trabajo.
Si el flujo de trabajo basado en código personalizado usa DynamicActivity
, se requieren algunos cambios en el CompileExpressions
método, como se muestra en el ejemplo de código siguiente.
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);
}
Hay varias diferencias en la sobrecarga de CompileExpressions
que compila expresiones de C# en una actividad dinámica.
El parámetro para
CompileExpressions
es unDynamicActivity
.El nombre de tipo y el espacio de nombres se recuperan mediante la propiedad
DynamicActivity.Name
.El valor de
TextExpressionCompilerSettings.ForImplementation
está establecido entrue
.CompiledExpressionInvoker.SetCompiledExpressionRootForImplementation
es llamado en lugar deCompiledExpressionInvoker.SetCompiledExpressionRoot
.
Para obtener más información sobre cómo trabajar con expresiones en el código, vea Creación de flujos de trabajo, actividades y expresiones mediante código imperativo.
Uso de expresiones de C# en flujos de trabajo XAML
Las expresiones de C# se admiten en flujos de trabajo XAML. Los flujos de trabajo XAML compilados se traducen a un tipo, y los flujos de trabajo XAML sueltos son cargados por el entorno de ejecución y se convierten en un árbol de actividades cuando se ejecuta el flujo de trabajo.
XAML compilado
Las expresiones de C# se admiten en flujos de trabajo XAML compilados que se compilan en un tipo como parte de un proyecto de flujo de trabajo de C# que tiene como destino .NET Framework 4.6.1. XAML compilado es el tipo predeterminado de creación de flujos de trabajo en Visual Studio y los proyectos de flujo de trabajo de C# creados en Visual Studio que tienen como destino .NET Framework 4.6.1 usan expresiones de C#.
XAML dinámico
Las expresiones de C# se admiten en flujos de trabajo XAML sueltos. El programa host de flujo de trabajo que carga e invoca el flujo de trabajo XAML flexible debe estar dirigido a .NET Framework 4.6.1, y CompileExpressions debe establecerse en true
(el valor predeterminado es false
). Para establecer CompileExpressions a true
, cree una instancia de ActivityXamlServicesSettings con su propiedad CompileExpressions establecida en true
, y pásela como parámetro a ActivityXamlServices.Load. Si CompileExpressions
no está establecido a true
, se lanzará un NotSupportedException con un mensaje similar al siguiente: 'Expression Activity type 'CSharpValue
1' requiere compilación para ejecutarse. Asegúrese de que se ha compilado el flujo de trabajo.
ActivityXamlServicesSettings settings = new ActivityXamlServicesSettings
{
CompileExpressions = true
};
DynamicActivity<int> wf = ActivityXamlServices.Load(new StringReader(serializedAB), settings) as DynamicActivity<int>;
Para obtener más información sobre cómo trabajar con flujos de trabajo XAML, consulta Serializar flujos de trabajo y actividades hacia y desde XAML.
Uso de expresiones de C# en servicios de flujo de trabajo XAMLX
Las expresiones de C# se admiten en los servicios de flujo de trabajo XAMLX. Cuando se hospeda un servicio de flujo de trabajo en IIS o WAS, no se requiere ningún paso adicional, pero si el servicio de flujo de trabajo XAML está autohospedado, se deben compilar las expresiones de C#. Para compilar las expresiones de C# en un servicio de flujo de trabajo XAMLX autohospedado, primero cargue el archivo XAMLX en WorkflowService
, a continuación, pase el Body
de WorkflowService
al método CompileExpressions
descrito en la sección Uso de expresiones de C# en flujos de trabajo de código. En el ejemplo siguiente, se carga un servicio de flujo de trabajo XAMLX, se compilan las expresiones de C# y, a continuación, se abre el servicio de flujo de trabajo y espera las solicitudes.
// 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();
Si las expresiones de C# no se compilan, la Open
operación se realiza correctamente, pero se producirá un error en el flujo de trabajo cuando se invoque. El método siguiente CompileExpressions
es el mismo que el método de la sección Anterior Uso de expresiones de C# en flujos de trabajo de código .
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);
}