Aracılığıyla paylaş


Kesinlik Temelli 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ımcısı'nı kullanarak 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. Çocuk 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);

Uyarı

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. WriteLine etkinliğinin Text bağımsız değişkeni ayarlanır ve iş akışı başlatılır. Bir etkinlik çocuk etkinlikleri içeriyorsa, inşaat yöntemi benzerdir. Aşağıdaki örnekte iki Sequence etkinlik içeren bir WriteLine 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şkenlerle, Sabit Değerlerle 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üldüğünde, Random.Next çağrısı gerçekleştirilir ve sonuç iş akışı tanımında sabit bir 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çindeki etkinlik her çalıştırıldığında değerlendirilir. İfadenin sonucu iş akışı değişkenine natanır ve bu sonuçlar iş akışındaki bir sonraki etkinlik tarafından kullanılır. çalışma zamanında n iş akışı değişkeninin ActivityContext değerine erişmek için gereklidir. Buna aşağıdaki lambda ifadesi kullanılarak erişilebilir.

Uyarı

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 natanır ve bu sonuçlar iş akışındaki bir sonraki etkinlik tarafından kullanılır. çalışma zamanında n iş akışı değişkeninin ActivityContext 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ürecektir. İfadeyi XAML ile uyumlu hale getirmek için, aşağıdaki örnekte gösterildiği gibi ExpressionServices ve Convert kullanın.

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.

Sabit İfadeler ve Referans Türleri

İş akışlarında değişmez değer ifadeleri Literal<T> etkinliği tarafından 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.")
}

String hariç herhangi bir referans türüyle bir literal ifade başlatmak geçersizdir. Aşağıdaki örnekte, Assign etkinliğinin Value özelliği, bir List<string> kullanılarak değişmez bir değer ifadesiyle 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: "Sabit değer yalnızca değer türlerini ve değişmez tür olan 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ü referans tipiyle literal ifade oluşturmak, iş akışının her bir örneği için referans tipinin yeni bir örneğini oluşturmaz. Bu sorunu çözmek için sabit ifadeyi, 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)")
}

InvokeMethod<TResult> etkinliği, Next sınıfının Random yöntemini çağırmak 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 metot olmadığından, Random sınıfının bir örneği TargetObject özelliği için 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 Assign<T> etkinliğini InvokeMethod<TResult> etkinliği yerine kullanmak daha kolay olacaktır. Ya Assign<T> ya da InvokeMethod<TResult> etkinlikleri tarafından nihayetinde çağrılan yöntem uzun süre çalışıyorsa, InvokeMethod<TResult> bir RunAsynchronously özelliğine sahip olduğu için bir avantajı vardır. Bu özellik olarak trueayarlandığı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.

Tartışmalar 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 iletilen iş akışı bağımsız değişkenlerini içerir. Imperatif kodda, iş akışı bağımsız değişkenleri yeni bir CLR türünde özellikler olarak belirtilir ve XAML'de x:Class ve x:Member kullanılarak 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, DynamicActivity'a bağımsız değişkenler eklenebilir. 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. Her bağımsız değişken için bir DynamicActivityProperty oluşturulur ve işlemin sonucu Result'nin DynamicActivity<TResult> bağımsız değişkenine 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. CodeActivity'den türetilen basit etkinlikler ve AsyncCodeActivity'den tü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. NativeActivity tabanlı bir etkinlik oluşturma örnekleri için bkz: NativeActivity Temel Sınıfı, Nasıl yapılır: Etkinlik Oluşturma ve Native Activity kullanarak Özel Bileşik örneği.

Activity'den kaynaklanan 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, Square'den türetilen bir Activity<int> etkinlik tanımlanmıştır. Square etkinliğinin InArgument<T> adlı tek bir Value'i vardır ve mantığını Sequence özelliğini kullanarak bir Implementation etkinlik belirterek 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 bir Square etkinlik içeren bir iş akışı tanımı WorkflowInvoker kullanılarak ç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ğeri karesine alma: 5Sonuç: 25