Munkafolyamatok, tevékenységek és kifejezések készítése imperatív kóddal
A munkafolyamat-definíció a konfigurált tevékenységobjektumok fája. Ez a tevékenységfa sokféleképpen definiálható, például az XAML kézi szerkesztésével vagy a Munkafolyamat Tervező használatával az XAML előállításához. Az XAML használata azonban nem követelmény. A munkafolyamat-definíciók programozott módon is létrehozhatók. Ez a témakör áttekintést nyújt a munkafolyamat-definíciók, tevékenységek és kifejezések kód használatával történő létrehozásáról. Példák az XAML-munkafolyamatok kód használatával történő használatára, lásd : Munkafolyamatok és tevékenységek szerializálása az XAML-be és onnan.
Munkafolyamat-definíciók létrehozása
A munkafolyamat-definíciók létrehozhatóak egy tevékenységtípus példányának példányainak példányosításával és a tevékenységobjektum tulajdonságainak konfigurálásával. A gyermektevékenységeket nem tartalmazó tevékenységek esetében ez néhány sornyi kóddal végezhető el.
Activity wf = new WriteLine
{
Text = "Hello World."
};
WorkflowInvoker.Invoke(wf);
Feljegyzés
A jelen témakör példái a minta-munkafolyamatok futtatására használhatók WorkflowInvoker . A munkafolyamatok meghívásáról, az argumentumok átadásáról és az elérhető különböző üzemeltetési lehetőségekről további információt a WorkflowInvoker és a WorkflowApplication használata című témakörben talál.
Ebben a példában egyetlen tevékenységből álló WriteLine munkafolyamat jön létre. A WriteLine tevékenység argumentuma Text be van állítva, és a rendszer meghívja a munkafolyamatot. Ha egy tevékenység gyermektevékenységeket tartalmaz, az építés módja hasonló. Az alábbi példa egy Sequence két WriteLine tevékenységet tartalmazó tevékenységet használ.
Activity wf = new Sequence
{
Activities =
{
new WriteLine
{
Text = "Hello"
},
new WriteLine
{
Text = "World."
}
}
};
WorkflowInvoker.Invoke(wf);
Objektum-inicializálók használata
A jelen témakör példái objektum inicializálási szintaxist használnak. Az objektum inicializálási szintaxisa hasznos lehet a munkafolyamat-definíciók kódban való létrehozásához, mivel hierarchikus nézetet biztosít a munkafolyamat tevékenységeiről, és megjeleníti a tevékenységek közötti kapcsolatot. Munkafolyamatok programozott létrehozásakor nincs szükség objektum inicializálási szintaxis használatára. Az alábbi példa funkcionálisan egyenértékű az előző példával.
WriteLine hello = new WriteLine();
hello.Text = "Hello";
WriteLine world = new WriteLine();
world.Text = "World";
Sequence wf = new Sequence();
wf.Activities.Add(hello);
wf.Activities.Add(world);
WorkflowInvoker.Invoke(wf);
Az objektum-inicializálókkal kapcsolatos további információkért lásd : Az objektumok inicializálása konstruktor meghívása nélkül (C# programozási útmutató) és útmutató: Objektum deklarálása objektum inicializáló használatával.
Változók, literális értékek és kifejezések használata
Amikor kóddal hoz létre munkafolyamat-definíciót, vegye figyelembe, hogy a munkafolyamat-definíció létrehozása során milyen kód fut, és hogy milyen kód fut a munkafolyamat egy példányának végrehajtása során. Az alábbi munkafolyamat célja például egy véletlenszerű szám létrehozása és a konzolba való írása.
Variable<int> n = new Variable<int>
{
Name = "n"
};
Activity wf = new Sequence
{
Variables = { n },
Activities =
{
new Assign<int>
{
To = n,
Value = new Random().Next(1, 101)
},
new WriteLine
{
Text = new InArgument<string>((env) => "The number is " + n.Get(env))
}
}
};
A munkafolyamat-definíciós kód végrehajtásakor a rendszer meghívja a hívást Random.Next
, és az eredmény a munkafolyamat-definícióban literális értékként lesz tárolva. A munkafolyamat számos példánya meghívható, és mindegyik ugyanazt a számot jeleníti meg. Ha azt szeretné, hogy a véletlenszerű számgenerálás a munkafolyamat végrehajtása során történjen, egy olyan kifejezést kell használni, amelyet a rendszer minden alkalommal kiértékel, amikor a munkafolyamat fut. Az alábbi példában egy Visual Basic-kifejezést használunk egy VisualBasicValue<TResult>.
new Assign<int>
{
To = n,
Value = new VisualBasicValue<int>("New Random().Next(1, 101)")
}
Az előző példában szereplő kifejezés egy és egy CSharpValue<TResult> C# kifejezéssel is implementálható.
new Assign<int>
{
To = n,
Value = new CSharpValue<int>("new Random().Next(1, 101)")
}
A C#-kifejezéseket az őket tartalmazó munkafolyamat meghívása előtt kell lefordítani. Ha a C#-kifejezések nincsenek lefordítva, NotSupportedException a rendszer a következőhöz hasonló üzenettel hívja meg a munkafolyamatot: Expression Activity type 'CSharpValue`1' requires compilation in order to run. Please ensure that the workflow has been compiled.
A Visual Studióban létrehozott munkafolyamatokat tartalmazó legtöbb forgatókönyvben a C#-kifejezések automatikusan lesznek lefordítva, de bizonyos helyzetekben, például kód-munkafolyamatokban a C#-kifejezéseket manuálisan kell lefordítani. A C#-kifejezések fordítására a C#-kifejezések témakör kód-munkafolyamatokban című szakaszában talál példát.
Az A VisualBasicValue<TResult> kifejezés a Visual Basic szintaxisában olyan kifejezést jelöl, amely r-értékként használható egy kifejezésben, a C# szintaxisban pedig egy CSharpValue<TResult> olyan kifejezést jelöl, amely r-értékként használható egy kifejezésben. Ezeket a kifejezéseket a rendszer minden alkalommal kiértékeli, amikor az adott tevékenységet végrehajtja. A kifejezés eredménye a munkafolyamat változóhoz n
van rendelve, és ezeket az eredményeket a munkafolyamat következő tevékenysége használja. A munkafolyamat-változó n
futásidejű értékének eléréséhez a ActivityContext szükséges. Ez a következő lambda kifejezéssel érhető el.
Feljegyzés
Vegye figyelembe, hogy mindkét kód példaként a C#-ot használja programozási nyelvként, de az egyik egy VisualBasicValue<TResult> , a másik pedig egy CSharpValue<TResult>. VisualBasicValue<TResult> és CSharpValue<TResult> Visual Basic- és C#-projektekben is használható. Alapértelmezés szerint a munkafolyamat-tervezőben létrehozott kifejezések megegyeznek az üzemeltetési projekt nyelvével. A munkafolyamatok kódban való létrehozásakor a kívánt nyelv a munkafolyamat-szerző saját belátása szerint történik.
Ezekben a példákban a kifejezés eredménye hozzá van rendelve a munkafolyamat változóhoz n
, és ezeket az eredményeket a munkafolyamat következő tevékenysége használja. A munkafolyamat-változó n
futásidejű értékének eléréséhez a ActivityContext szükséges. Ez a következő lambda kifejezéssel érhető el.
new WriteLine
{
Text = new InArgument<string>((env) => "The number is " + n.Get(env))
}
A lambdakifejezésekről további információt a Lambda-kifejezések (C#-referencia) vagy a Lambda-kifejezések (Visual Basic) című témakörben talál.
A Lambda-kifejezések nem szerializálhatók XAML formátumban. Ha lambdakifejezésekkel próbál szerializálni egy munkafolyamatot, LambdaSerializationException a következő üzenet jelenik meg: "Ez a munkafolyamat a kódban megadott lambdakifejezéseket tartalmazza. Ezek a kifejezések nem XAML szerializálhatók. A munkafolyamat XAML-szerializálhatóvá tételéhez használja a VisualBasicValue/VisualBasicReference vagy a ExpressionServices.Convert(lambda) parancsot. Ez a lambda-kifejezéseket kifejezési tevékenységekké alakítja." Ha kompatibilissé szeretné tenni ezt a kifejezést az XAML-vel, használja és Converthasználja ExpressionServices az alábbi példában látható módon.
new WriteLine
{
//Text = new InArgument<string>((env) => "The number is " + n.Get(env))
Text = ExpressionServices.Convert((env) => "The number is " + n.Get(env))
}
A VisualBasicValue<TResult> is használható. Ne feledje, hogy Visual Basic-kifejezés használatakor nincs szükség lambda kifejezésre.
new WriteLine
{
//Text = new InArgument<string>((env) => "The number is " + n.Get(env))
//Text = ExpressionServices.Convert((env) => "The number is " + n.Get(env))
Text = new VisualBasicValue<string>("\"The number is \" + n.ToString()")
}
Futásidőben a Visual Basic-kifejezések LINQ-kifejezésekké lesznek lefordítva. Mindkét előző példa szerializálható az XAML-hez, de ha a szerializált XAML-t a munkafolyamat-tervezőben szeretné megtekinteni és szerkeszteni, használja VisualBasicValue<TResult> a kifejezéseket. A szerializált munkafolyamatok, amelyeket használnak ExpressionServices.Convert
, megnyithatók a tervezőben, de a kifejezés értéke üres lesz. A munkafolyamatok XAML-be való szerializálásával kapcsolatos további információkért lásd : Munkafolyamatok és tevékenységek szerializálása az XAML-be és onnan.
Literálkifejezések és hivatkozástípusok
A konstans kifejezéseket a tevékenység jeleníti meg a Literal<T> munkafolyamatokban. Az alábbi WriteLine tevékenységek funkcionálisan egyenértékűek.
new WriteLine
{
Text = "Hello World."
},
new WriteLine
{
Text = new Literal<string>("Hello World.")
}
Érvénytelen a literális kifejezés inicializálása bármilyen hivatkozástípussal, kivéve String. Az alábbi példában egy Assign tevékenység tulajdonsága Value egy literális kifejezéssel inicializálódik egy List<string>
.
new Assign
{
To = new OutArgument<List<string>>(items),
Value = new InArgument<List<string>>(new List<string>())
},
A tevékenységet tartalmazó munkafolyamat ellenőrzésekor a következő érvényesítési hiba jelenik meg: "A literál csak az értéktípusokat és a nem módosítható System.String típust támogatja. A System.Collections.Generic.List'1[System.String] típus nem használható literálként." Ha a munkafolyamat meghívása történik, a rendszer az InvalidWorkflowException érvényesítési hiba szövegét tartalmazza. Ez egy érvényesítési hiba, mert egy hivatkozástípussal rendelkező literális kifejezés létrehozása nem hoz létre új hivatkozástípus-példányt a munkafolyamat minden példányához. A probléma megoldásához cserélje le a literális kifejezést egy olyan kifejezésre, amely létrehozza és visszaadja a referenciatípus új példányát.
new Assign
{
To = new OutArgument<List<string>>(items),
Value = new InArgument<List<string>>(new VisualBasicValue<List<string>>("New List(Of String)"))
},
A kifejezésekről további információt a Kifejezések című témakörben talál.
Metódusok meghívása objektumokon kifejezések és az InvokeMethod-tevékenység használatával
A InvokeMethod<TResult> tevékenység a .NET-keretrendszer osztályainak statikus és példánymetóriák meghívására használható. A jelen témakör egy korábbi példájában véletlenszerű szám jött létre az Random osztály használatával.
new Assign<int>
{
To = n,
Value = new VisualBasicValue<int>("New Random().Next(1, 101)")
}
A InvokeMethod<TResult> tevékenység az osztály metódusának meghívására NextRandom is használható.
new InvokeMethod<int>
{
TargetObject = new InArgument<Random>(new VisualBasicValue<Random>("New Random()")),
MethodName = "Next",
Parameters =
{
new InArgument<int>(1),
new InArgument<int>(101)
},
Result = n
}
Mivel Next ez nem statikus módszer, az Random osztály egy példánya lesz megadva a TargetObject tulajdonsághoz. Ebben a példában egy új példány egy Visual Basic-kifejezéssel jön létre, de korábban is létrehozhatta, és egy munkafolyamat-változóban tárolta. Ebben a példában egyszerűbb lenne a tevékenységet használni a Assign<T>InvokeMethod<TResult> tevékenység helyett. Ha a metódushívást végül vagy a Assign<T>InvokeMethod<TResult> tevékenységek hosszú ideig futtatják, akkor előnyt élvez, InvokeMethod<TResult> mivel rendelkezik egy tulajdonságtal RunAsynchronously . Ha ez a tulajdonság be van állítva true
, a meghívott metódus aszinkron módon fog futni a munkafolyamat tekintetében. Ha más tevékenységek párhuzamosak, akkor a metódus aszinkron végrehajtása során nem lesznek blokkolva. Ha a meghívandó metódusnak nincs visszatérési értéke, akkor InvokeMethod<TResult> a metódus meghívásának megfelelő módja.
Argumentumok és dinamikus tevékenységek
A munkafolyamat-definíciók kódban jönnek létre a tevékenységek tevékenységfába való összeállításával, valamint a tulajdonságok és argumentumok konfigurálásával. A meglévő argumentumok kötöttek lehetnek, de új argumentumok nem adhatók hozzá a tevékenységekhez. Ide tartoznak a gyökértevékenységnek átadott munkafolyamat-argumentumok. Az imperatív kódban a munkafolyamat-argumentumok egy új CLR-típus tulajdonságaiként vannak megadva, az XAML-ben pedig a használatával x:Class
és x:Member
a . Mivel nem jön létre új CLR-típus, amikor a munkafolyamat-definíció memórián belüli objektumok fajaként jön létre, argumentumokat nem lehet hozzáadni. Az argumentumok azonban hozzáadhatók egy DynamicActivity. Ebben a példában egy DynamicActivity<TResult> olyan létrejön, amely két egész argumentumot vesz fel, összeadja őket, és visszaadja az eredményt. Minden DynamicActivityProperty argumentumhoz létrejön egy A, és a művelet eredménye hozzá lesz rendelve a .
InArgument<int> Operand1 = new InArgument<int>();
InArgument<int> Operand2 = new InArgument<int>();
DynamicActivity<int> wf = new DynamicActivity<int>
{
Properties =
{
new DynamicActivityProperty
{
Name = "Operand1",
Type = typeof(InArgument<int>),
Value = Operand1
},
new DynamicActivityProperty
{
Name = "Operand2",
Type = typeof(InArgument<int>),
Value = Operand2
}
},
Implementation = () => new Sequence
{
Activities =
{
new Assign<int>
{
To = new ArgumentReference<int> { ArgumentName = "Result" },
Value = new InArgument<int>((env) => Operand1.Get(env) + Operand2.Get(env))
}
}
}
};
Dictionary<string, object> wfParams = new Dictionary<string, object>
{
{ "Operand1", 25 },
{ "Operand2", 15 }
};
int result = WorkflowInvoker.Invoke(wf, wfParams);
Console.WriteLine(result);
A dinamikus tevékenységekkel kapcsolatos további információkért lásd : Tevékenység létrehozása a futtatókörnyezetben.
Lefordított tevékenységek
A dinamikus tevékenységek egy olyan tevékenység definiálására szolgálnak, amely kóddal tartalmaz argumentumokat, de a tevékenységek kódban is létrehozhatók, és típusok szerint fordíthatók le. Egyszerű tevékenységek hozhatók létre, amelyek származnak CodeActivity, és aszinkron tevékenységek származnak AsyncCodeActivity. Ezek a tevékenységek argumentumokkal, visszaadott értékekkel és imperatív kóddal definiálhatják logikájukat. Az ilyen típusú tevékenységek létrehozásának példáiért lásd: CodeActivity Alaposztály és Aszinkron tevékenységek létrehozása.
A származtatott NativeActivity tevékenységek imperatív kóddal definiálhatják a logikájukat, és olyan gyermektevékenységeket is tartalmazhatnak, amelyek meghatározzák a logikát. Teljes hozzáféréssel rendelkeznek a futtatókörnyezet funkcióihoz, például könyvjelzők létrehozásához. Példák a -based tevékenység létrehozására NativeActivity: NativeActivity Base Class, How to: Create an Activity, and the Custom Composite using Native Activity sample.
Azok a tevékenységek, amelyek a logikájuk meghatározásából Activity származnak, kizárólag gyermektevékenységek használatával. Ezeket a tevékenységeket általában a munkafolyamat-tervezővel hozzák létre, de kóddal is definiálhatók. Az alábbi példában egy Square
olyan tevékenység van definiálva, amely a következőből Activity<int>
származik: . A Square
tevékenység egyetlen InArgument<T> névvel Value
rendelkezik, és a tulajdonságot használó tevékenység megadásával Sequence határozza meg a Implementation logikáját. A Sequence tevékenység egy WriteLine tevékenységet és egy Assign<T> tevékenységet tartalmaz. Ez a három tevékenység együttesen valósítja meg a tevékenység logikáját Square
.
class Square : Activity<int>
{
[RequiredArgument]
public InArgument<int> Value { get; set; }
public Square()
{
this.Implementation = () => new Sequence
{
Activities =
{
new WriteLine
{
Text = new InArgument<string>((env) => "Squaring the value: " + this.Value.Get(env))
},
new Assign<int>
{
To = new OutArgument<int>((env) => this.Result.Get(env)),
Value = new InArgument<int>((env) => this.Value.Get(env) * this.Value.Get(env))
}
}
};
}
}
Az alábbi példában egy egyetlen Square
tevékenységből álló munkafolyamat-definíciót hív meg a rendszer WorkflowInvoker.
Dictionary<string, object> inputs = new Dictionary<string, object> {{ "Value", 5}};
int result = WorkflowInvoker.Invoke(new Square(), inputs);
Console.WriteLine("Result: {0}", result);
A munkafolyamat meghívásakor a következő kimenet jelenik meg a konzolon:
Az érték guggolása: 5
Eredmény: 25
Visszajelzés
https://aka.ms/ContentUserFeedback.
Hamarosan elérhető: 2024-ben fokozatosan kivezetjük a GitHub-problémákat a tartalom visszajelzési mechanizmusaként, és lecseréljük egy új visszajelzési rendszerre. További információ:Visszajelzés küldése és megtekintése a következőhöz: