Wyrażenia języka C#
Począwszy od programu .NET Framework 4.5, wyrażenia języka C# są obsługiwane w programie Windows Workflow Foundation (WF). Nowe projekty przepływu pracy języka C# utworzone w programie Visual Studio 2012 przeznaczone dla platformy .NET Framework 4.5 używają wyrażeń języka C#, a projekty przepływu pracy języka Visual Basic używają wyrażeń języka Visual Basic. Istniejące projekty przepływu pracy programu .NET Framework 4 korzystające z wyrażeń języka Visual Basic można migrować do programu .NET Framework 4.6.1 niezależnie od języka projektu i są obsługiwane. Ten temat zawiera omówienie wyrażeń języka C# w programie WF.
Używanie wyrażeń języka C# w przepływach pracy
Używanie wyrażeń języka C# w Projektant przepływu pracy
Począwszy od programu .NET Framework 4.5, wyrażenia języka C# są obsługiwane w programie Windows Workflow Foundation (WF). Projekty przepływu pracy języka C# utworzone w programie Visual Studio 2012 przeznaczone dla platformy .NET Framework 4.5 używają wyrażeń języka C#, podczas gdy projekty przepływu pracy języka Visual Basic używają wyrażeń języka Visual Basic. Aby określić żądane wyrażenie języka C#, wpisz je w polu z etykietą Wprowadź wyrażenie języka C#. Ta etykieta jest wyświetlana w oknie właściwości po wybraniu działania w projektancie lub w działaniu w projektancie przepływu pracy. W poniższym przykładzie dwa WriteLine
działania znajdują się wewnątrz Sequence
elementu NoPersistScope
.
Uwaga
Wyrażenia języka C# są obsługiwane tylko w programie Visual Studio i nie są obsługiwane w projektancie ponownie hostowanego przepływu pracy. Aby uzyskać więcej informacji na temat nowych funkcji platformy WF45 obsługiwanych w ponownym projektancie, zobacz Obsługa nowych funkcji programu Workflow Foundation 4.5 w Projektant ponownego hostowanego przepływu pracy.
Zgodność z poprzednimi wersjami
Obsługiwane są wyrażenia języka Visual Basic w istniejących projektach przepływu pracy .NET Framework 4 C#, które zostały zmigrowane do programu .NET Framework 4.6.1. Gdy wyrażenia języka Visual Basic są wyświetlane w projektancie przepływu pracy, tekst istniejącego wyrażenia języka Visual Basic jest zastępowany wartością ustawioną w języku XAML, chyba że wyrażenie języka Visual Basic jest prawidłową składnią języka C#. Jeśli wyrażenie języka Visual Basic jest prawidłową składnią języka C#, zostanie wyświetlone wyrażenie. Aby zaktualizować wyrażenia języka Visual Basic do języka C#, można je edytować w projektancie przepływu pracy i określić równoważne wyrażenie języka C#. Nie jest wymagane zaktualizowanie wyrażeń języka Visual Basic do języka C#, ale po zaktualizowaniu wyrażeń w projektancie przepływu pracy są konwertowane na język C# i mogą nie zostać przywrócone do języka Visual Basic.
Używanie wyrażeń języka C# w przepływach pracy kodu
Wyrażenia języka C# są obsługiwane w przepływach pracy opartych na kodzie programu .NET Framework 4.6.1, ale zanim przepływ pracy będzie można wywołać, należy skompilować wyrażenia języka C# przy użyciu polecenia TextExpressionCompiler.Compile. Autorzy przepływów pracy mogą użyć CSharpValue
funkcji do reprezentowania wartości r wyrażenia oraz CSharpReference
do reprezentowania wartości l wyrażenia. W poniższym przykładzie przepływ pracy jest tworzony przy użyciu Assign
działania i WriteLine
działania zawartego Sequence
w działaniu. Parametr A CSharpReference
jest określony dla To
argumentu Assign
, i reprezentuje wartość l wyrażenia. Argument a CSharpValue
jest określony dla Value
argumentu Assign
, i dla Text
argumentu WriteLine
, i reprezentuje wartość r dla tych dwóch wyrażeń.
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);
Po utworzeniu przepływu pracy wyrażenia języka C# są kompilowane przez wywołanie metody pomocniczej CompileExpressions
, a następnie wywoływanie przepływu pracy. Poniższy przykład to CompileExpressions
metoda .
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);
}
Uwaga
Jeśli wyrażenia języka C# nie są kompilowane, NotSupportedException jest zgłaszany, gdy przepływ pracy jest wywoływany z komunikatem podobnym do następującego: Expression Activity type 'CSharpValue
1' wymaga kompilacji w celu uruchomienia. Upewnij się, że przepływ pracy został skompilowany".
Jeśli niestandardowy przepływ pracy oparty na kodzie używa DynamicActivity
metody , wymagane są pewne zmiany CompileExpressions
w metodzie, jak pokazano w poniższym przykładzie kodu.
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);
}
Istnieje kilka różnic w CompileExpressions
przeciążeniu, które kompiluje wyrażenia języka C# w działaniu dynamicznym.
Parametr to
CompileExpressions
DynamicActivity
.Nazwa typu i przestrzeń nazw są pobierane przy użyciu
DynamicActivity.Name
właściwości .TextExpressionCompilerSettings.ForImplementation
jest ustawiona natrue
wartość .CompiledExpressionInvoker.SetCompiledExpressionRootForImplementation
jest wywoływanaCompiledExpressionInvoker.SetCompiledExpressionRoot
zamiast .
Aby uzyskać więcej informacji na temat pracy z wyrażeniami w kodzie, zobacz Tworzenie przepływów pracy, działań i wyrażeń przy użyciu kodu imperatywnego.
Używanie wyrażeń języka C# w przepływach pracy XAML
Wyrażenia języka C# są obsługiwane w przepływach pracy XAML. Skompilowane przepływy pracy XAML są kompilowane w typie, a luźne przepływy pracy XAML są ładowane przez środowisko uruchomieniowe i kompilowane w drzewie działań podczas wykonywania przepływu pracy.
Skompilowany kod Xaml
Wyrażenia języka C# są obsługiwane w skompilowanych przepływach pracy XAML, które są kompilowane do typu w ramach projektu przepływu pracy języka C#, który jest przeznaczony dla programu .NET Framework 4.6.1. Skompilowany kod XAML jest domyślnym typem tworzenia przepływu pracy w programie Visual Studio, a projekty przepływu pracy języka C# utworzone w programie Visual Studio przeznaczone dla platformy .NET Framework 4.6.1 używają wyrażeń języka C#.
Luźne Xaml
Wyrażenia języka C# są obsługiwane w luźnych przepływach pracy XAML. Program hosta przepływu pracy, który ładuje i wywołuje luźny przepływ pracy XAML, musi być przeznaczony dla programu .NET Framework 4.6.1 i CompileExpressions musi być ustawiony na true
wartość (wartość domyślna to false
). Aby ustawić CompileExpressions true
wartość , utwórz ActivityXamlServicesSettings wystąpienie z właściwością CompileExpressions ustawioną na true
, a następnie przekaż je jako parametr do ActivityXamlServices.Load. Jeśli CompileExpressions
nie ustawiono true
wartości , NotSupportedException zostanie zgłoszony komunikat podobny do następującego: Expression Activity type 'CSharpValue
1' wymaga kompilacji w celu uruchomienia. Upewnij się, że przepływ pracy został skompilowany".
ActivityXamlServicesSettings settings = new ActivityXamlServicesSettings
{
CompileExpressions = true
};
DynamicActivity<int> wf = ActivityXamlServices.Load(new StringReader(serializedAB), settings) as DynamicActivity<int>;
Aby uzyskać więcej informacji na temat pracy z przepływami pracy XAML, zobacz Serializowanie przepływów pracy i działań do i z XAML.
Używanie wyrażeń języka C# w usługach przepływu pracy XAMLX
Wyrażenia języka C# są obsługiwane w usługach przepływu pracy XAMLX. Jeśli usługa przepływu pracy jest hostowana w usługach IIS lub WAS, nie są wymagane żadne dodatkowe kroki, ale jeśli usługa przepływu pracy XAML jest hostowana samodzielnie, należy skompilować wyrażenia języka C#. Aby skompilować wyrażenia języka C# w samoobsługowej usłudze przepływu pracy XAMLX, najpierw załaduj plik XAMLX do WorkflowService
elementu , a następnie przekaż element WorkflowService
Body
do CompileExpressions
metody opisanej w poprzedniej sekcji Używanie wyrażeń języka C# w sekcji przepływów pracy kodu. W poniższym przykładzie jest ładowana usługa przepływu pracy XAMLX, skompilowane są wyrażenia języka C#, a następnie usługa przepływu pracy jest otwierana i czeka na żądania.
// 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();
Jeśli wyrażenia języka C# nie zostaną skompilowane, operacja zakończy się pomyślnie, Open
ale przepływ pracy zakończy się niepowodzeniem po wywołaniu. Poniższa CompileExpressions
metoda jest taka sama jak metoda z poprzedniej sekcji Używanie wyrażeń języka C# w sekcji przepływów pracy kodu.
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);
}