Kesin Kod Kullanarak İş Akışları, Etkinlikler ve İfadeler Yazma
İş akışı tanımı, yapılandırılmış etkinlik nesnelerinin ağacıdır. Bu etkinlik ağacı, XAML'yi el ile düzenleyerek veya XAML oluşturmak için İş Akışı Tasarım Aracı kullanılarak da dahil olmak üzere birçok yolla tanımlanabilir. Ancak XAML kullanımı bir gereksinim değildir. İş akışı tanımları program aracılığıyla da oluşturulabilir. Bu konu, kod kullanarak iş akışı tanımları, etkinlikler ve ifadeler oluşturmaya genel bir bakış sağlar. Kod kullanarak XAML iş akışlarıyla çalışma örnekleri için bkz . XAML'ye ve XAML'den İş Akışlarını ve Etkinlikleri SeriLeştirme.
İş Akışı Tanımları Oluşturma
Bir etkinlik türünün örneği oluşturularak ve etkinlik nesnesinin özellikleri yapılandırılarak iş akışı tanımı oluşturulabilir. Alt etkinlikler içermeyen etkinlikler için bu işlem birkaç kod satırı kullanılarak gerçekleştirilebilir.
Activity wf = new WriteLine
{
Text = "Hello World."
};
WorkflowInvoker.Invoke(wf);
Not
Bu konudaki örnekler örnek iş akışlarını çalıştırmak için kullanılır WorkflowInvoker . İş akışlarını çağırma, bağımsız değişkenleri geçirme ve kullanılabilen farklı barındırma seçenekleri hakkında daha fazla bilgi için bkz . WorkflowInvoker ve WorkflowApplication Kullanma.
Bu örnekte, tek WriteLine bir etkinlik içeren bir iş akışı oluşturulur. Etkinliğin WriteLineText bağımsız değişkeni ayarlanır ve iş akışı çağrılır. Bir etkinlik çocuk etkinlikleri içeriyorsa, inşaat yöntemi benzerdir. Aşağıdaki örnekte iki WriteLine etkinlik içeren bir Sequence etkinlik kullanılır.
Activity wf = new Sequence
{
Activities =
{
new WriteLine
{
Text = "Hello"
},
new WriteLine
{
Text = "World."
}
}
};
WorkflowInvoker.Invoke(wf);
Nesne Başlatıcıları Kullanma
Bu konudaki örneklerde nesne başlatma söz dizimi kullanılır. İş akışındaki etkinliklerin hiyerarşik bir görünümünü sağladığından ve etkinlikler arasındaki ilişkiyi gösterdiğinden, kodda iş akışı tanımları oluşturmak için nesne başlatma söz dizimi yararlı bir yol olabilir. Program aracılığıyla iş akışları oluştururken nesne başlatma söz dizimlerini kullanmanız gerekmez. Aşağıdaki örnek, işlevsel olarak önceki örne eşdeğerdir.
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);
Nesne başlatıcıları hakkında daha fazla bilgi için bkz . Nasıl yapılır: Oluşturucu Çağırmadan Nesneleri Başlatma (C# Programlama Kılavuzu) ve Nasıl yapılır: Nesne Başlatıcı Kullanarak Nesne Bildirme.
Değişkenler, Değişmez Değerler ve İfadelerle Çalışma
Kodu kullanarak iş akışı tanımı oluştururken, iş akışı tanımının oluşturulması sırasında hangi kodun yürütüldüğünü ve bu iş akışının bir örneğinin yürütülmesi kapsamında hangi kodun yürütüldüğünü unutmayın. Örneğin, aşağıdaki iş akışının rastgele bir sayı oluşturması ve konsola yazması amaçlanmıştır.
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))
}
}
};
Bu iş akışı tanım kodu yürütürken çağrısı Random.Next
yapılır ve sonuç iş akışı tanımında değişmez değer olarak depolanır. Bu iş akışının birçok örneği çağrılabilir ve tümü aynı numarayı görüntüler. Rastgele sayı oluşturma işleminin iş akışı yürütmesi sırasında gerçekleşmesi için, iş akışı her çalıştırıldığında değerlendirilen bir ifade kullanılmalıdır. Aşağıdaki örnekte, bir Visual Basic ifadesi ile VisualBasicValue<TResult>birlikte kullanılır.
new Assign<int>
{
To = n,
Value = new VisualBasicValue<int>("New Random().Next(1, 101)")
}
Önceki örnekteki ifade bir CSharpValue<TResult> ve C# ifadesi kullanılarak da uygulanabilir.
new Assign<int>
{
To = n,
Value = new CSharpValue<int>("new Random().Next(1, 101)")
}
C# ifadelerinin, bunları içeren iş akışı çağrılmadan önce derlenmesi gerekir. C# ifadeleri derlenmiyorsa, iş akışı aşağıdakine benzer bir iletiyle çağrıldığında bir NotSupportedException oluşturulur: Expression Activity type 'CSharpValue`1' requires compilation in order to run. Please ensure that the workflow has been compiled.
Visual Studio'da oluşturulan iş akışlarını içeren çoğu senaryoda C# ifadeleri otomatik olarak derlenir, ancak kod iş akışları gibi bazı senaryolarda C# ifadelerinin el ile derlenmesi gerekir. C# ifadelerini derleme örneği için C# İfadeleri konusunun Kod iş akışlarında C# ifadelerini kullanma bölümüne bakın.
A VisualBasicValue<TResult> , Visual Basic söz diziminde bir ifadede r değeri olarak kullanılabilen bir ifadeyi, CSharpValue<TResult> C# söz diziminde bir ifadede r-değeri olarak kullanılabilen bir ifadeyi temsil eder. Bu ifadeler, içeren etkinlik her yürütülürken değerlendirilir. İfadenin sonucu iş akışı değişkenine n
atanır ve bu sonuçlar iş akışındaki bir sonraki etkinlik tarafından kullanılır. çalışma zamanında ActivityContext iş akışı değişkeninin n
değerine erişmek için gereklidir. Buna aşağıdaki lambda ifadesi kullanılarak erişilebilir.
Not
Bu kodların her ikisinin de programlama dili olarak C# kullandığını, ancak birinin bir VisualBasicValue<TResult> kullandığını, birinin ise bir CSharpValue<TResult>kullandığını unutmayın. VisualBasicValue<TResult> ve CSharpValue<TResult> hem Visual Basic hem de C# projelerinde kullanılabilir. Varsayılan olarak, iş akışı tasarımcısında oluşturulan ifadeler barındırma projesinin diliyle eşleşmektedir. Kodda iş akışları oluştururken istenen dil iş akışı yazarının takdirine bağlıdır.
Bu örneklerde ifadenin sonucu iş akışı değişkenine n
atanır ve bu sonuçlar iş akışındaki bir sonraki etkinlik tarafından kullanılır. çalışma zamanında ActivityContext iş akışı değişkeninin n
değerine erişmek için gereklidir. Buna aşağıdaki lambda ifadesi kullanılarak erişilebilir.
new WriteLine
{
Text = new InArgument<string>((env) => "The number is " + n.Get(env))
}
Lambda ifadeleri hakkında daha fazla bilgi için bkz . Lambda İfadeleri (C# başvurusu) veya Lambda İfadeleri (Visual Basic).
Lambda ifadeleri XAML biçiminde serileştirilebilir değildir. Bir iş akışını lambda ifadeleriyle seri hale getirme girişiminde bulunulduysa, şu iletiyle bir LambdaSerializationException oluşturulur: "Bu iş akışı kodda belirtilen lambda ifadelerini içeriyor. Bu ifadeler XAML serileştirilebilir değildir. İş akışınızı XAML serileştirilebilir hale getirmek için VisualBasicValue/VisualBasicReference veya ExpressionServices.Convert(lambda) kullanın. Bu, lambda ifadelerinizi ifade etkinliklerine dönüştürür." Bu ifadeyi XAML ile uyumlu hale getirmek için aşağıdaki örnekte gösterildiği gibi ve ConvertkullanınExpressionServices.
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> da kullanılabilir. Visual Basic ifadesi kullanılırken lambda ifadesinin gerekli olmadığını unutmayın.
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()")
}
Çalışma zamanında Visual Basic ifadeleri LINQ ifadelerinde derlenir. Önceki örneklerin her ikisi de XAML için serileştirilebilir, ancak serileştirilmiş XAML'nin iş akışı tasarımcısında görüntülenmesi ve düzenlenmesi amaçlanıyorsa ifadeleriniz için kullanın VisualBasicValue<TResult> . Kullanan ExpressionServices.Convert
serileştirilmiş iş akışları tasarımcıda açılabilir, ancak ifadenin değeri boş olur. İş akışlarını XAML'ye seri hale getirme hakkında daha fazla bilgi için bkz . XAML'ye ve XAML'den İş Akışlarını ve Etkinlikleri Seri Hale Getirme.
Değişmez İfadeler ve Başvuru Türleri
Değişmez değer ifadeleri, iş akışlarında etkinlik tarafından Literal<T> temsil edilir. Aşağıdaki WriteLine etkinlikler işlevsel olarak eşdeğerdir.
new WriteLine
{
Text = "Hello World."
},
new WriteLine
{
Text = new Literal<string>("Hello World.")
}
dışında Stringherhangi bir başvuru türüyle değişmez değer ifadesi başlatmak geçersizdir. Aşağıdaki örnekte, bir Assign etkinliğin Value özelliği kullanılarak değişmez değer ifadesiyle List<string>
başlatılır.
new Assign
{
To = new OutArgument<List<string>>(items),
Value = new InArgument<List<string>>(new List<string>())
},
Bu etkinliği içeren iş akışı doğrulandığında şu doğrulama hatası döndürülür: "Değişmez değer yalnızca değer türlerini ve sabit tür System.String'i destekler. System.Collections.Generic.List'1[System.String] türü değişmez değer olarak kullanılamaz." İş akışı çağrılırsa, doğrulama hatası metnini içeren bir InvalidWorkflowException oluşturulur. Bu bir doğrulama hatasıdır çünkü başvuru türüyle değişmez değer ifadesi oluşturmak, iş akışının her örneği için başvuru türünün yeni bir örneğini oluşturmaz. Bu sorunu çözmek için değişmez değeri, başvuru türünün yeni bir örneğini oluşturan ve döndüren ifadeyle değiştirin.
new Assign
{
To = new OutArgument<List<string>>(items),
Value = new InArgument<List<string>>(new VisualBasicValue<List<string>>("New List(Of String)"))
},
İfadeler hakkında daha fazla bilgi için bkz . İfadeler.
İfadeleri ve InvokeMethod Etkinliğini Kullanarak Nesnelerde Yöntemleri Çağırma
Etkinlik, InvokeMethod<TResult> .NET Framework'teki sınıfların statik ve örnek yöntemlerini çağırmak için kullanılabilir. Bu konudaki önceki bir örnekte, sınıfı kullanılarak Random rastgele bir sayı oluşturulmuştur.
new Assign<int>
{
To = n,
Value = new VisualBasicValue<int>("New Random().Next(1, 101)")
}
Etkinliği, InvokeMethod<TResult> sınıfının yöntemini Random çağırmak Next için de kullanılmış olabilir.
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
}
Next Statik bir yöntem olmadığından, özelliği için TargetObject sınıfının bir örneği Random sağlanır. Bu örnekte, Visual Basic ifadesi kullanılarak yeni bir örnek oluşturulur, ancak daha önce oluşturulmuş ve bir iş akışı değişkeninde depolanmış da olabilir. Bu örnekte etkinlik yerine InvokeMethod<TResult> etkinliği kullanmak Assign<T> daha kolay olacaktır. Ya da Assign<T>InvokeMethod<TResult> etkinlikleri tarafından sonunda çağrılan yöntem çağrısı uzun süre çalışıyorsa, InvokeMethod<TResult> bir özelliği olduğundan bir avantajı vardır RunAsynchronously . Bu özellik olarak true
ayarlandığında, çağrılan yöntem iş akışıyla ilgili olarak zaman uyumsuz olarak çalışır. Diğer etkinlikler paralelse, yöntem zaman uyumsuz olarak yürütülürken engellenmez. Ayrıca, çağrılacak yöntemin dönüş değeri yoksa, InvokeMethod<TResult> yöntemini çağırmak için uygun yoldur.
Bağımsız Değişkenler ve Dinamik Etkinlikler
Kodda bir iş akışı tanımı, etkinlikleri bir etkinlik ağacında bir araya getirerek ve tüm özellikleri ve bağımsız değişkenleri yapılandırarak oluşturulur. Mevcut bağımsız değişkenler bağlanabilir, ancak etkinliklere yeni bağımsız değişkenler eklenemez. Bu, kök etkinliğe geçirilen iş akışı bağımsız değişkenlerini içerir. Kesinlik temelli kodda, iş akışı bağımsız değişkenleri yeni bir CLR türünde özellikler olarak belirtilir ve XAML'de ve x:Member
kullanılarak x:Class
bildirilir. Bir iş akışı tanımı bellek içi nesnelerin ağacı olarak oluşturulduğunda oluşturulan yeni bir CLR türü olmadığından, bağımsız değişkenler eklenemez. Ancak, bağımsız değişkenler öğesine DynamicActivityeklenebilir. Bu örnekte, iki tamsayı bağımsız değişkeni alan, bunları bir araya getiren ve sonucu döndüren bir DynamicActivity<TResult> oluşturulur. DynamicActivityProperty Her bağımsız değişken için bir oluşturulur ve işlemin sonucu bağımsız değişkenine ResultDynamicActivity<TResult>atanır.
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);
Dinamik etkinlikler hakkında daha fazla bilgi için bkz . Çalışma Zamanında Etkinlik Oluşturma.
Derlenmiş Etkinlikler
Dinamik etkinlikler, kod kullanarak bağımsız değişkenler içeren bir etkinliği tanımlamanın bir yoludur, ancak etkinlikler kodda da oluşturulabilir ve türlerde derlenebilir. 'den türetilen basit etkinlikler ve 'den CodeActivityAsyncCodeActivitytüretilen zaman uyumsuz etkinlikler oluşturulabilir. Bu etkinlikler bağımsız değişkenlere sahip olabilir, değerleri döndürebilir ve kesinlik temelli kod kullanarak mantıklarını tanımlayabilir. Bu tür etkinlikleri oluşturma örnekleri için bkz . CodeActivity Temel Sınıfı ve Zaman Uyumsuz Etkinlikler Oluşturma.
öğesinden NativeActivity türetilen etkinlikler, kesinlik temelli kodu kullanarak kendi mantığını tanımlayabilir ve ayrıca mantığı tanımlayan alt etkinlikleri de içerebilir. Ayrıca, çalışma zamanının yer işaretleri oluşturma gibi özelliklerine de tam erişimi vardır. Tabanlı etkinlik oluşturma NativeActivityörnekleri için bkz. NativeActivity Temel Sınıfı, Nasıl yapılır: Etkinlik Oluşturma ve Yerel Etkinlik kullanarak Özel Bileşik örneği.
'den Activity türetilen etkinlikler, mantıklarını yalnızca alt etkinliklerin kullanımıyla tanımlar. Bu etkinlikler genellikle iş akışı tasarımcısı kullanılarak oluşturulur, ancak kod kullanılarak da tanımlanabilir. Aşağıdaki örnekte, 'den Activity<int>
türetilen bir Square
etkinlik tanımlanmıştır. Etkinliğin Square
adlı tek InArgument<T> bir adı Value
vardır ve özelliğini kullanarak Implementation bir Sequence etkinlik belirterek mantığını tanımlar. Etkinlik Sequence bir WriteLine etkinlik ve bir Assign<T> etkinlik içerir. Bu üç etkinlik birlikte etkinliğin Square
mantığını uygular.
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))
}
}
};
}
}
Aşağıdaki örnekte, tek Square
bir etkinlik içeren bir iş akışı tanımı kullanılarak WorkflowInvokerçağrılır.
Dictionary<string, object> inputs = new Dictionary<string, object> {{ "Value", 5}};
int result = WorkflowInvoker.Invoke(new Square(), inputs);
Console.WriteLine("Result: {0}", result);
İş akışı çağrıldığında konsolda aşağıdaki çıkış görüntülenir:
Değerin karesini alma: 5
Sonuç: 25