WWF etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
WWF etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

Pazartesi, Nisan 12, 2010

Visual Studio 2010 – RTM

Visual Studio 2010 çıktı.

Uzun bir gelişme sürecinin ardından Visual Studio 2010 resmi olarak satışa sunuldu.Visual Studio 2010

IDE üzerinde WPF ‘in nimetlerinden yararlanılarak yapılan değişiklikler, WWF ‘in tasarımın ve akış tiplerinin yenilenmesi, F# dilinin entegre edilmesi, MVC 2 ile beraber gelmesi ve diğer bir çok özelliği ile bugün VS2010 çıkmış bulunuyor. Deneme sürümünü indirip kurmak isteyenler aşağıda verecek olduğum linkten yararlanabilirler. Almak isteyenler için ise Visual Studio 2010 Ultimate satış fiyatı $11850. :)

http://www.microsoft.com/visualstudio/en-us/download

Pazar, Mart 28, 2010

WF - Conditions

.Net Frameowork 4.0 ile Windows Workflow Foundation iş akışı yapısının 4 sürümünün çıkışı çok yaklaşmışken biz WWF 3.x sürümleri yardımı ile iş akışı süreçlerini örnekler yardımı ile incelemeye devam ediyor olacağız. Bu güne kadar iş akışına temel bir giriş yaptık ve araç kutusunda yer alan iş akışı bileşenlerini nasıl kullanabileceğimizi tek tek incelemeye başladık. Bu inceleme işlemlerini örnekler ile zenginleştirerek ise bizlerin kullanımı esnasında dikkat edecek olduğumuz noktalara da değinmeye çalıştık. Bu formatta devam ederek Windows Workflow Foundation ile Condition (Koşul) kavramını inceliyor olacağız.

Condition denildiği zaman aklımıza While ve IfElseBranchActivity bileşenlerinde süreci durduracak ya da başka bir işlem yapmamıza olanak tanıyacak bir kriter olarak gelmektedir. bir önceki Parallel Activity yazımızda While döngüsüne denk gelen aktivite bileşenini kullanırken kısmen bu özelliği nasıl kullanabileceğimize kısaca göz atma fırsatı bulduk. Ancak Condition 'ı tamamen nasıl kullanabileceğimizi bu yazımızın içerisinde kullanıyor olacağız.

Şimdi Condition yapısını örnek üzerinde inceleyelim. Bu örneğimizi yaparken Visual Studio 2010 ide sini ve .Net Framework 3.0 sürümünü kullanıyor olacağız.

Uygulamayı geliştirmek için Sequential Workflow Console Application tasarımında proje oluşturduktan sonra ekrana bir adet While aktivitesi sürüklüyoruz.

WF,Conditions
Tasarım ekranı üzerine sağ tıklama yaptıktan sonra özellikler ekranından Condition değerleri verebileceğimiz bölüme ulaşabilmemiz mümkündür. Kullanabileceğimiz Condition tipleri iki adettir. Bunlar;
WF,Conditions şeklinde yer almaktadır. Bu koşul tiplerinden en hızlı çalışanı ve en çok tercih edileni Code Condition 'dır. Bizde koşulları incelerken ilk olarak kod üzerinden inceliyor olacağız.

Bu işlem için kod tarafına geçerek koşul olarak kullanacak olduğumuz rakam artışını sağlayan method hazırlıyoruz.

private int count;
private void ContinueLooping(object sender, ConditionalEventArgs args)
{
    args.Result = (count < 10);
}

Condition olarak kullanacak olduğumuz metodu hazırladıktan sonra tasarım ekranında While aktivitesinin içerisine ve aktivitenin sonuna olmak üzere iki tane kod aktivite ekliyor ve aşağıdaki kod parçalarını yazıyoruz.

private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
    Console.WriteLine("Merhaba {0}",count);
    count++;
}

private void codeActivity2_ExecuteCode(object sender, EventArgs e)
{
    Console.ReadLine();
}

Şimdi ise While Aktivitesine koşulu eklemeye sıra geldi. Bunun için özellikler ekranında condition özelliğine code condition seçeneğini seçtikten sonra Conditions özelliğine bizim oluşturmuş olduğumuz ContinueLooping() 'i gösteriyoruz.

WF,Conditions

Yapmış olduğumuz bu işlemler sonrasında koşulları da aktif olarak kullandığımız uygulamanın çalıştığı anki ekran görüntüsü aşağıdaki gibi olacaktır.

WF,Conditions

Kod yardımı ile oluşturmuş olduğumuz koşulu işlediğimizde sorunsuzca çalıştığını görmüş olduk. Kod koşulları dışında kullanabileceğimiz bir diğer seçenek ise kural bazlı koşullar (rule conditions) dır. Bu seçeneği kullandığımız durumlarda bir öncekinden farklı olarak koşulları girebileceğimiz bir ekran karşımıza çıkacak ve kriterimizi buraya girmiş olacağız. Bu yapmış olduğumuz değişiklikleri ve eklentileri arka plan Workflow Foundation xml içerisinde saklayarak bizim While ya da ifElseBranch aktivitelerini kullanacağımız durumlarda kullanmamıza olanak tanıyacaktır.

Kural bazlı aktiviteleri kullanmak için ilk yapılması gereken koşul kullanılacak olan aktivinin özelliklerinden ki bu bizim örneğimiz için while aktivitesi oluyor, Condition özelliğini Rule Condition olarak belirtiyoruz.

WF,Conditions

Condition tipi seçme işlemini tamamladıktan sonra ConditionName özelliğine istediğimiz herhangi bir değer verdikten sonra sağ tarafında yer alan butona tıklayarak kriterleri girecek olduğumuz ekranın açılmasına olanak tanıyoruz.

WF,Conditions

Yukarıdaki ekranda yapmış olduğumuz işlemlerden de görmüş olduğunuz üzere daha önceki örneğimizde kod yardımı ile oluşturmuş olduğumuz sayacın 10 dan ufak olana kadar çalışmasını sağlayan bir metot hazırlamış ve kullanmıştık. Bu kullanımda ise bu tür işlemler yapılmasına gerek yoktur. Eklenmiş olunan kriterlere istenen değerler atanarak While aktivitesinde sorunsuzca kullanılabildi. Ayrnıca karşımıza çıkan bu ekranın diğer özelliklerinden biri de başka kriterler ekleyebilir, bu kriterleri düzenleyebilir, silebilir ya da isimlerini değiştirebiliriz.

Şimdi ise yapmış olduğumuz işlemler sonrasında bakalım ekran görüntüsü ya da çalışma mantığında değişen bir şey olmuş mu?

WF,Conditions

Gördüğümüz kadarıyla herşey sorunsuz gözüküyor. Bu da bize hem Code Condition hem de Rule Condition ile elde ettiğimiz sonuçların aynı olduğunu göstermektedir. Aralarında en büyük fark kullanım şekillleridir. Ancak dikkat edeceğiniz üzere kullanım şekilleri farklı olmakla birlikte aslında yazılan kod parçaları ve işlem adımları birbirlerine çok benzerdir.

Şimdi üzerinde denemeler yapmış olduğumuz örneği biraz daha karmaşık bir duruma getirirken hem de ifElse aktivitesinde de koşulları nasıl kullanacağımıza göz atıyor olalım.

Yapacak olduğumuz işlem için tasarım ekranında şu şekilde bir değişiklik yapmamız gerekmektedir. While aktivitesinin içerisine bir Sequence aktivite ekledikten sonra onun içerisine de ifElse aktivite ekliyoruz. Sonrasında ise ifElse aktivitesinde olacak sonuçları gözlemleyebilmek için Code Activity 'ler ekleyerek tasarım ekranında yapılacak olan değişikleri tamamlıyoruz.

WF,Conditions
Tasarım ekranında yapacak olduğumuz değişiklikleri tamamladıktan sonra sıra koşulları belirlemeye geldi. Bunun için ise ifElse aktivitesinin özelliklerinden Condition seçeneğine Rule Activity değerini atadıktan sonra aktivitenin 5 ten ufak olan değer için merhaba yazmasını diğerleri için ise Hoşçakal yazmasını sağlayacağız. Hoşçakal yazması için sağ taraftaki kod aktivitesine Console.WriteLine("Hoşçakal"); count++; kodları yazılır.

WF,Conditions

Yapmış olduğumuz işlemler sonrasında yapmış olduğumuz işlemler konusunda istediğimizi alabilmiş miyizi kontrol edebilmek için uygulamayı çalıştırıyor ve sonuçları gözlemliyoruz.

WF,Conditions

Sonuç oldukça başarılı :)

Bu yazımızda Workflow Foundation 'da Condition kavramını inceleye çalıştık. Condition tiplerinden hem Code Condition olarak nasıl yapabileceğimizi hem de Rule Condition olarak nasıl kullanabileceğimizi örnekler yardımı ile inceledikten sonra While ve ifElse aktiviteleri üzerinde Condition tipleri yardımı ile örnekler yaparak yazımızı tamamladık.

Umarım yararlı olabilmiştir.

Turhal Temizer

info@turhaltemizer.com

Salı, Mart 16, 2010

WPF 4 & .Net Framework 4 - Workflow Designer Oluşturmak - II

Windows Workflow Foundation (WF) 4 ve Windows Presentation Foundation (WPF) 4 'ün artık tam sürümlerine kavuşmalarına sayılı günler kala biz WPF ile nasıl bir iş akış tasarım ekranı yapabiliriz diyerek kendimize sorduktan sonra adım adım bu işlemleri gerçekleştirmeye başladık. Yapmış olduğumuz işlemler sonrasında Araç çubuğu (ToolBox), tasarım ekranı (activity Designer), özellikler penceresi (Property Inspector) olan temel arayüze kavuşmuş bulunduk.



.Net Framework 4.0 ve WPF 4.0 'ın bize sağlamış olduğunu esneklik ve kolaylık yardımı ile yukarıda görmüş olduğunuz işlemi oldukça basit bir şekilde gerçekleştirebilmiştik. Şimdi ise harici aktivitelerimizi kullanmak için oluşturmuş olduğumuz Custom Activities projesinin içerisine visual studio içerisinde yer alan şablonlardan Activity Library seçeneğini kullanarak harici bir aktiviteyi nasıl oluşturabileceğimizi detaylı bir şekilde inceliyor olacağız.

O zaman Custom Activity projesinde yer alan Prompt aktivitesini Activity Designer 'ı ekleyerek bu daha görsel bir akışı nasıl hazırlayabileceğimize göz atalım.

Custom activities projesinde aktivitelerin tasarımsal öğelerini kullanabilmek için System.Activities.Presentation 'ı referans olarak ekliyoruz.



Sonrasında CustomActivities projesine Activity Designer ekleyeceğiz. Ama bu sefer bu bölümü biz hazırlamayacağız. .Net 4.0 ile birlikte workflow şablonlarının içerisinde yer alanı kullanacağız. Bunun için projenin üzerinde sağ tıklama yaptıktan sonra add new item seçeneği yardımı ile açılan ekranda workflow seçeneğini seçiyor ve .Net 4.0 'ın içerisinde yer alan Activity Designer şablonunu projeye ekliyoruz. İsmini de BasitTasarım.xaml olarak belirtiyoruz.



Activity Designer 'ı projeye eklediğimizde bize XAML kod ile düzenleme yapabileceğimiz ve oluşan değişiklikler sonucundaki tasarımı görüntüleyebileceğimiz tasarım ekranı ile gelmektedir.



Activity Designer 'ın XAML ile esnekleşmiş tasarımının içerisine iş akışımızı temsil edecek basit bir tasarım ekliyoruz. Buna benzer tasarımları Expression Studio ailesinde yer alan Expression Design ürünü ile hazırlayabilmeniz mümkündür. Bu ürün size yapmış olduğunuz tasarımların XAML çıktılarını vereceği için rahatlıkla kullanabiliyor olabileceksiniz.

Oluşturmuş olduğumuz tasarımın XAML kodları aşağıdaki şekildedir.

<sap:ActivityDesigner x:Class="CustomActivities.BasitTasarim"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sap="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation"
    xmlns:sapv="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation" mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Collapsible="True" d:DesignHeight="130" d:DesignWidth="206">

    <Viewbox x:Name="Group" Width="75px">
        <Canvas Width="143.047" Height="159.025">
            <Ellipse x:Name="Ellipse" Width="32.3333" Height="28.3334" Canvas.Left="20.9435" Canvas.Top="8.66254" Stretch="Fill" StrokeThickness="7" StrokeLineJoin="Round" Stroke="#FF000000"/>
            <Path x:Name="Path" Width="21.3251" Height="32.8953" Canvas.Left="53.6983" Canvas.Top="41.0262" Stretch="Fill" StrokeThickness="7" StrokeLineJoin="Round" Stroke="#FF000000" Data="F1 M 57.1983,44.5262L 71.5234,64.9118L 57.1983,70.4215"/>
            <Path x:Name="Line" Width="42.8127" Height="34.5482" Canvas.Left="68.5744" Canvas.Top="55.3513" Stretch="Fill" StrokeThickness="7" StrokeLineJoin="Round" Stroke="#FF000000" Data="F1 M 72.0744,86.3994L 107.887,58.8513"/>
            <Path x:Name="Line_0" Width="45.0165" Height="20.2231" Canvas.Left="74.635" Canvas.Top="77.3898" Stretch="Fill" StrokeThickness="7" StrokeLineJoin="Round" Stroke="#FF000000" Data="F1 M 78.135,94.1129L 116.152,80.8898"/>
            <Path x:Name="Path_1" Width="45.5675" Height="17.4684" Canvas.Left="74.635" Canvas.Top="102.734" Stretch="Fill" StrokeThickness="7" StrokeLineJoin="Round" Stroke="#FF000000" Fill="#FFFFFFFF" Data="F1 M 78.135,106.234L 110.642,115.05L 116.702,116.702"/>
            <Path x:Name="Path_2" Width="39.5069" Height="30.1405" Canvas.Left="69.6763" Canvas.Top="114.304" Stretch="Fill" StrokeThickness="7" StrokeLineJoin="Round" Stroke="#FF000000" Fill="#FFFFFFFF" Data="F1 M 73.1763,117.804L 95.7658,133.782L 105.683,140.945"/>
            <Path x:Name="Path_3" Width="20.2231" Height="33.4463" Canvas.Left="33.8636" Canvas.Top="88.4091" Stretch="Fill" StrokeThickness="7" StrokeLineJoin="Round" Stroke="#FF000000" Data="F1 M 50.5868,91.9091L 37.3636,106.234L 49.4848,118.355"/>
            <Rectangle x:Name="Rectangle" Width="143.047" Height="159.025" Canvas.Left="0" Canvas.Top="0" Stretch="Fill" StrokeThickness="2" StrokeLineJoin="Round" Stroke="#FF000000"/>
        </Canvas>
    </Viewbox>


</sap:ActivityDesigner>

Değişiklikler sonrasında oluşan görüntü ise aşağıdaki gibi olacaktır.



Yapmış olduğumuz değişiklikten sonra projeyi derleyip, iş akışı tasarım uygulamasını hazırlamış olduğumuz projeye geçiyoruz. Bir önceki yazımızdan da hatırlayacağınız üzere CustomActivities projesini HostApp projesine referans göstererek içerisinde yapmış olduğumuz değişikliklerin ve eklemiş olduğumuz değişiklikleri kullanabilmemize olanak tanımış oluyoruz.

Oluşturmuş olduğumuz harici aktivitenin HostApp projesinde gözükebilmesi için, MainWindow.xaml 'in *.cs kısmını açarak aşağıdaki değişiklikleri yapmaya başlıyoruz.

İlk olarak yapmamız gereken CustomActivities projesini kod ekranında kullanabilmek olacaktır. Bunun için aşağıdaki isim alanlarını ekliyoruz.

using CustomActivities;
using System.ComponentModel;
using System.Activities.Presentation.Metadata;

Daha öncedn oluşturmuş olduğumuz RegisterMetaData isimli metodu prompt aktivitesini alacak şekilde aşağıdaki gibi yeniden güncelliyoruz.

private void RegisterMetaData()
{
    (new DesignerMetadata()).Register();

    AttributeTableBuilder builder = new AttributeTableBuilder();

    builder.AddCustomAttributes(typeof(Prompt), new DesignerAttribute(typeof(BasitTasarim)));

    MetadataStore.AddAttributeTable(builder.CreateTable());
}

Son yapmış olduğumuz bu değişiklik sonrasında oluşan görünüm aşağıdaki gibi olacaktır.



Ayrıca yapmış olduğumuz iş akışı tasarım ekranına bizim hazırlamış olduğumuz toolbox üzerinde yer alan bileşenleri sürürkleyip bırakabilir. Sürüklediğimiz bileşenlere de değerler atayabilmemiz mümkündür.

Peki, biz bu hazırlamış olduğumuz harici aktivitelere özellikler ekranından değer alabilecek bir bileşen ekleyebilmemiz mümkün müdür şeklinde aklımıza sorular gelmektedir. Cevabı tabikii evet olacaktır. Bunun için CustomActivities projesinin içerisine eklemiş olduğumuz BasitTasarim aktivitesinin XAML kod tarafına bir adet textbox kontrolü ekliyor olacağız.

Tasarımı daha derli toplu olması için ViewBox görünüm nesnesinin üst kısmına ekran üzerine yerleşim konusunda bizlere yardım olan <StackPanel> 'i ekledikten sonra TextBox bileşenini ekleyebilmemiz mümkündür.

<StackPanel>
    <Viewbox x:Name="Group" Width="75" >
        ...
    </Viewbox>
    <TextBox Text="{Binding Path=ModelItem.Text, Mode=TwoWay}" />
</StackPanel>

Text değerini dışarıdan gelecek olan bir değerden alacağını belirttikten sonra yapmış olduğumuz değişiklikleri kaydediyor ve projemizi derledikten sonra çalıştırıyoruz.



Evet sonuç tam istediğimiz gibi olmuştur...

Bu yazımızda anlattıklarımızı toparlamak gerekirse, harici bir iş akışı aktivitesini nasıl oluşturmamız gerektiğini, görsellik nasıl kazandırabileceğimizi ve bu tasarım içerisine görsellik dışında değerleri atayabileceğimiz kontrolleri nasıl ekleyebileceğimizi incelemeye çalıştık. Bir sonraki yazımızda ise eklemiş olduğumuz bileşenlerin iş akışı tasarım ekranında derlenebilmesine göz atıyor olacağız.

Umarım yararlı olabilmiştir.

Kaynak
MSDN

Turhal Temizer

info@turhaltemizer.com

Cumartesi, Mart 13, 2010

WPF 4 & .Net Framework 4 - Workflow Designer Oluşturmak - I

Windows Workflow Foundation (WF) ile incelemelerimizi bir süredir .Net 3.0 kütüphanesi ve Visual Studio IDE 'si üzerinde alışık olduğumuz tasarım ekranı ile incelemeye ve uygulamalarımızı geliştirmeye çalışıyorduk. Ancak çok yakın bir zaman içerisinde .Net 4.0 'ın final sürümüne kavuşacağını düşünerek bu yazımızı Visual Studio 2010 IDE sinde .Net 4.0 ile Worklow Designer programlama modelini incelemeye çalışıyor olacağız.

Not: Worfklow Foundation 4.0 ile ilgili detaylı bilgi için Burak Selim Şenyurt 'un yazmış olduğu bu güzel yazıyı incelemenizi tavsiye ediyorum. Çünkü bu yazımızda uygulama bazında WF 4.0 'ı inceliyor olacağız.

Yakın zaman içerisinde karşımıza çıkacak olan Visual Studio 2010 bilindiği üzere WPF ile yeniden tasarlandı. Daha esnek ve daha kullanışlı bir tasarım ile karşımıza çıktı. Özellikle WPF 'in esnekliğini Visual Studio 2010 üzerinde kullanabileceğimize hiç şüphemiz yoktur. VS2010 'da bu değişiklikler olurken bir yandan da yenilenen görünümü, tasarım yapısı ve WPF ile hazırlanmış iş akışlarını tasarlayabildiğimiz Activity Library ekranı yardımı ile biz geliştiriciler için kullanım kolaylaşmıştır.

Bu kadar yenilenen tasarımdan bahsettikten sonra artık uygulama geliştirmeye geliştirmeye başlayabiliriz. Yazımızında başında da bahsettiğimiz gibi uygulamalarımızı VS2010 ve .Net 4.0 ile geliştiriyor olacağız. Uygulamamız esnasında bir WPF uygulamasında iş akışı süreçlerini kullanıyor olacağız.

İlk olarak VS2010 yardımı ile WPF uygulaması oluşturuyoruz.



Projemiz başarılı bir şekilde oluşturulduktan sonra proje özellikleri ekranında yapacak olduğumuz ufak birkaç işlem bulunmaktadır. Projelerde varsayılan target Framework .Net Framework 4 Client Profile seçeneği seçili olarak gelmektedir. Biz bunu .Net Framework 4 seçeneği seçili olacak şekilde değiştiriyoruz.



Bu ekranda yapmış olduğumuz değişiklik esnasında karşımıza Target Framework 'u değiştirmek istiyor musunuz? şekilde soru soran bir ekran çıkacaktır. Evet dedikten sonra artık .Net Framework 4 'ün bütün nimetlerinde faydalanır duruma geliyoruz.

Peki biz bu değişikliği neden yaptık. Çünkü belirli bir şablon tipine dahil olan bir proje yi oluşturduğumuzda yalnızca bu proje tipinde kullanılabilecek isim alanlarının ve araçlarının olduğu daha özelleştirilmiş bir framework bizlere sunulmaktadır. Sebebi ise o proje geliştirilirken onun ile ilgisi olmayan framework kısımlarını kullanmamaktır. Bunun en büyük faydası ile Garbage collector 'un daha rahat çalışması ve çabuk derleme şeklinde yorumlayabiliriz. Ancak biz bu yazımızda WF tasarım ekranını kendimiz oluşturmaya çalışacağımız için framework 'un tamamına ihtiyacamız olacaktır. Çünkü biraz önceki kısıtlı framework 'te WF geliştirmemize olanak tanıyacak olan dll 'ler yer almamaktaydı. Bu kısa bilgiyi de öğrendikten sonra işlemlerimizi yapmaya devam edebiliriz.

Şimdi uygulamamıza bir tane Class Library ekliyoruz. Sonrasında bir adet sınıf oluşturuyoruz ve bu sınıfı CodeActivity 'den türetiyoruz. Sonrasında ise aşağıdaki kodları ekliyoruz.

namespace CustomActivities
{
    using System;
    using System.Activities;
    using System.Activities.Statements;

    public class Prompt : CodeActivity
    {
        public string Text { get; set; }
        public string Response { get; set; }

        protected override void Execute(CodeActivityContext context)
        {
           throw new NotImplementedException();
        }

         public static Activity GetSimpleSequence()
         {
             return new Sequence
             {
                 Activities =
                 {
                    ;  new Prompt(),
                    ;  new Assign()
                 }
             };
        }
    }
}

Bu işlem sonrasında projeyi derliyor ve oluşturmuş olduğumuz WPF uygulamasına Add Reference ekranında projeler kısmından ekliyoruz.



Sonrasında WPF uygulamasına referans eklemeye devam ediyoruz. CodeActivity 'yi kullandığımız için projemizde System.Activities, System.Activities.Core.Presentation, System.Activities.Presentation DLL 'lerinin projeye ekli olması gerekmektedir.



Bu işlemi de tamamladıktan sonra hazırlayacak olduğumuz Workflow Designer 'i oluşturmaya başlayabiliriz.

WPF uygulaması içerisinde yer alan MainWindows.xaml üzerinde işlemler yapağız. Oluşturacak Workflow Designer 'ı WPF Grid içerisinde düzenliyor olacağız. Yaptığımız işlem sonrasında ise WorkflowDesigner 'ın içerisine Sequence aktivitenin tasarım ekranında yer alacaktır.

Şimdi tasarım ekranı üzerinde birkaç düzenleme yapalım. İlk olarak standart olması açısından tasarım ekranının boyutlarını 800x600 olarak belirliyoruz.



Biz bu işlemleri yaparken IDE 'nin yaptığımız değişiklikleri XAML kod üzerine yansıttığını unutmayalım. Yani istersek bu işlemlerin hepsinin XAML üzerinde nesnelerin özelliklerine değerler vererekte yapabilmemiz mümkündür.

Tasarım ekranı üzerinde yapmış olduğumuz işlemler sonrasında şimdi de Grid 'i özelleştireceğiz. ColumnDefinitions özelliklerine CollectionEditor yardımı ile birkaç kolon ekleyip özelliklerine değerler atayacağız.



Collection Editor 'u açtıktan sonra 3 tane kolon ekliyoruz.



Kolonları ekledik. Ancak genişlik boyutunu gördüğünüz kadarıyla 4* şeklindedir. Peki bu yıldız nedir? Kısaca açıklayalım.

Yıldız değeri kullanılan satır ya da sütunlar değişebilir şekilde kullanılabilir. Örneğin * olan değerler ilk durumda satır ve sütünlar bir kez kullanılabilirken 2* olanlar iki kez kullanılabilmektedir.

Grid üzerinde yapmış olduğumuz değişiklikler XAML kod tarafına nasıl yansıdığına kısaca göz atmak gerekirse şu şekilde olmuştur.

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition Width="4*" />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
</Grid>

Herşey güzel. Bu grid üzerine neden 3 kolon koyduk? Hemen açıklayalım. Visual Studio IDE 'sinden referans alarak ve kendi çapımızda bir Workflow ekranı yaptığımızı düşünürsek, sol tarafta ToolBox (araç kutusu) orta tarafta Workflow Designer (İş akışı tasarım) en sağ tarafta da Property Inspector (özellikler( bölümü yer alacaktır.

XAML tarafındaki işlemleri şimdilik tamamladık. Sırada kod tarafında yapacağımız işlemler var. Bunun için MainWindows.xaml 'in kod ekranını açarak işlemlerimize başlıyoruz.

İlk olarak kullanacak olduğumuz isim alanlarını ekliyor olacağız.

using System.Activities.Core.Presentation;
using System.Activities.Presentation;
using System.Activities.Presentation.Toolbox;
using System.Activities.Statements;

Kullanacak olduğumuz isim alanları hazır durumdadır. Bir Workflow Designer yaptığımıza göre WorkflowDesigner sınıfını proje içerisinde kullanıyor olamak gerekiyor.

public partial class MainWindow : Window
{
    private WorkflowDesigner wd;

    public MainWindow()
    {
        InitializeComponent();
    }
}

Şimdi ise Ekran üzerinde WorkflowDesigner oluşturabilmek için AddDesigner isimli private bir metot oluşturacağız. Bunun yardımı ile iş akışı tasarım ekranının oluşmasını ve grid 'in hangi kısmında duracağını belirtiyor olacağız.

private void AddDesigner()
{
    //WorkflowDesigner sınıfı çağırılır.
    this.wd = new WorkflowDesigner();

    //Workflow Designer 'in ekran üzerinde nerede olacağını belirtiyoruz.
    Grid.SetColumn(this.wd.View, 1);

    //Varsayılan olarak bir Sequence oluşturuyour.
    this.wd.Load(new Sequence());

    //WorkflowDesigner 'i grid 'e ekliyoruz.
    grid1.Children.Add(this.wd.View);
}

Çağırmış olduğumuz Sequence sınıfının DesignerMetaData() sınıfını içinde barındıran bir sınıf ile kayıt etmemiz gerekmektedir. Bu sebeple RegisterMetaData() isimli bir metot daha oluşturarak bu işlemi gerçekleştiriyor olalım.

//Sequence sınıfının kaydı yapılıyor.
private void RegisterMetaData()
{
    (new DesignerMetadata()).Register();
}

Sırada yapacak olduğumuz işlem ise MainWindow ekranı oluşturulurken hazırlamış olduğumuz metotları çağırmak olacaktır.

public MainWindow()
{
    InitializeComponent();
    this.AddDesigner();
     this.RegisterMetaData();

}

Çağırma işlemleri de tamamlandıktan sonra artık workflow tasarım ekranımızın ilk adımınının nasıl olduğuna göz atabiliriz. Bunun için projeyi çalıştırmak yeterli olacaktır.



İstediğimizi başardık. Artık WPF uygulamasını bir iş akışı tasarımcısı yapma konusunda ilk adımımızı attık ve tasarım bölümünü oluşturduk. Sırada yapacak olduğuğumuz işlem ise ToolBox 'ı ve Property Inspector 'u oluşturmak olacaktır.

Oluşturacak olduğumuz bu iki bölümü yaparken Workflow Designer 'ı oluşturduğumuz gibi basit bir şekilde olacaktır. Çünkü .net 4.0 'ın yapısı bize daha da fazla şekilde esnek, geliştirilebilir ve genişletirilebilir bir yapı sunmaktadır.

WPF Grid içerisine ToolBox 'ı oluşturma işlemine başlıyoruz. Bu işlem için GetToolboxControl isminde bir metot kullanırken bunu ToolboxControl den oluşturuyor olacağız.

Toolbox Category Item Collection 'nun içerisine iki değer atayacağız. Bunlar;
1. CustomActivitiex.Prompt aktivitesi,
2. System.Activities.Statements.Sequence aktivitesi olacaktır.

private ToolboxControl GetToolboxControl()
{
    // Toolbox kontrol oluşturuluyor.
    ToolboxControl ctrl = new ToolboxControl();

    //Kategorideki elemanlar için koleksiyon oluşuturuluyor.
    ToolboxCategory categoryItems = new ToolboxCategory ("category1");

    //Toolbox öğeleri oluşturulur.
    ToolboxItemWrapper tool = new ToolboxItemWrapper ("CustomActivities.Prompt",     "CustomActivities", null, null);

    ToolboxItemWrapper tool2 = new ToolboxItemWrapper ("System.Activities.Statements.Sequence",
"System.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35", null, "Sequence");

    // Toolbox öğeleri kategoriye ekleniyor.
    categoryItems.Add(tool);
    categoryItems.Add(tool2);

    //kategoriye eklenen toolbox kontrolleri.
    ctrl.Categories.Add(categoryItems);

    return ctrl;
}

Toolbox kontrol 'ün içeriğini kontrolduğumuza göre şimdi de toolbox 'ı eklemek için AddToolBox() isimli metodu oluşturuyor.

private void AddToolBox()
{
    ToolboxControl tc = GetToolboxControl();
    Grid.SetColumn(tc, 0);
    grid1.Children.Add(tc);
}

SSon olarak bu metodu mainwindow metodunda çağırdıktan sonra uygulamamızı derleyerek oluşan sonuca bir göz atıyoruz.



İş akışı tasarım ekranı oluşturulması adımları olan Toolbox ve Workflow Designer bölümlerinin oluşturulmasını başarılı bir şekilde tamamlamış bulunuyoruz. Son adımımız olan Property Inspector bölümünün eklenmesi aşamasını şimdi yapıyor olalım.

Property Inspector ekranını kullanmak için her zamanki gibi eklememize yarayan bir metot oluşturacağız. Sonrasında ise bu metodu formun oluştuğu anda çağırarak işlemlerimizi tamamlıyor olacağız.

Şu ana kadar yapmış olduğumuz işlemler esnasında gördüğümüz kadarıyla aslında temek bir iş akışı tasarım ekranı oluşturmak oldukça kolaylaştırılmıştır. Özellikler ekranını hazırlarken de bu kolaylıklardan yararlanarak basitçe işlemlerimizi tamamlıyor olacağız. WorkflowDesigner sınıfının UIElement lerinden olan PropertyInspectorView yardımı ile özellikler ekranını rahatlıkla ekleyeceğiz.

private void AddPropertyInspector()
{
   Grid.SetColumn(wd.PropertyInspectorView, 2);
   grid1.Children.Add(wd.PropertyInspectorView);
}

Property Inspector ekranını da eklediğimize göre artık uygulamamızın en son haline bakabiliriz.



Sonuç tam istediğimiz gibi gözükmektedir.

Şu ana kadar yazmış olduğumuz kod parçalarının birleştirilmiş hallerine göz atmak gerekirse sonuç aşağıdaki gibi olacaktır.

using System.Windows;

using System.Activities.Core.Presentation;
using System.Activities.Presentation;
using System.Activities.Presentation.Toolbox;
using System.Activities.Statements;
using System.Windows.Controls;

namespace HostApp
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
    public partial class MainWindow : Window
    {
        private WorkflowDesigner wd;

        public MainWindow()
        {
            InitializeComponent();
            this.AddDesigner();
            this.RegisterMetaData();
            this.AddToolBox();
            this.AddPropertyInspector();
        }

        private void AddDesigner()
        {
             //WorkflowDesigner sınıfı çağırılır.
             this.wd = new WorkflowDesigner();

             //Workflow Designer 'in ekran üzerinde nerede olacağını belirtiyoruz.
             Grid.SetColumn(this.wd.View, 1);

             //Varsayılan olarak bir Sequence oluşturuyour.
             this.wd.Load(new Sequence ());

             //WorkflowDesigner 'i grid 'e ekliyoruz.
             grid1.Children.Add (this.wd.View);
        }

        //Sequence sınıfının kaydı yapılıyor.
        private void RegisterMetaData()
        {
            (new DesignerMetadata()).Register ();
        }

        //Toolbox oluşturuluyor.
        private ToolboxControl GetToolboxControl()
        {
            // Toolbox kontrol oluşturuluyor.
            ToolboxControl ctrl = new ToolboxControl();

            //Kategorideki elemanlar için koleksiyon oluşuturuluyor.
            ToolboxCategory categoryItems = new ToolboxCategory("category1");

            //Toolbox öğeleri oluşturulur.
            ToolboxItemWrapper tool = new ToolboxItemWrapper("CustomActivities.Prompt", "CustomActivities", null, null);

             ToolboxItemWrapper tool2 = new ToolboxItemWrapper("System.Activities.Statements.Sequence",
                  "System.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35", null, "Sequence");

             // Toolbox öğeleri kategoriye ekleniyor.
             categoryItems.Add(tool);
             categoryItems.Add(tool2);

            //kategoriye eklenen toolbox kontrolleri.
            ctrl.Categories.Add (categoryItems);
            return ctrl;
       }

       //Ekrana toolbox bölümü eklendi.
       private void AddToolBox()
       {
            ToolboxControl tc = GetToolboxControl();
            Grid.SetColumn(tc, 0);
            grid1.Children.Add(tc);
       }

       //Özellikler (Property Inspector) bölümü ekleniyor.
       private void AddPropertyInspector()
       {
             Grid.SetColumn (wd.PropertyInspectorView, 2);
             grid1.Children.Add (wd.PropertyInspectorView);
        }
    }
}

Sonuç olarak .Net Framework 'un ve WPF 'in esnekliğinden yararlanarak çok hızlı bir şekilde iş akışı tasarım ekranının başlangıç düzeyini oluşturmuş bulunuyoruz. Bu yazımızı takiben aynı uygulama üzerinden geliştirmelerimize devam ederken CustomActivity kütüphanesini daha aktif kullanarak harici aktiviteler oluşturuyor olacağız.

Umarım yararlı olabilmiştir.
Kaynak
MSDN

Turhal Temizer

info@turhaltemizer.com

Pazar, Şubat 14, 2010

WF - Parallel Activity

Windows Workflow (WF) teknolojisini kullanarak uygulama geliştirmek istediğimizde kullanabileceğimiz adımları incelemeye devam ediyoruz. Şu ana kadar incelemiş olduğumuz iş akışı tipleri sürekli olarak tek sequence activty 'den oluşmakta ve tek yönlü bir iş akışı süreci oluşmaktadır. Eğer ki şu ana kadar görmüş olduğumuz yöntemler de akış esnasında herhangi bir adım sonrasında aynı anda iki akış başlatmak istediğimizde bu durumu gerçekleştirme şansımız olmayacaktı. Eğer ki bir şekilde yapmaya çalışırsakta oldukça uğraştırıcı bir yöntem olacaktır. Bu tür ihtiyaçlarımızı karşılamak için toolbox 'ımızın içeriğini incelediğimizde parallel activity bileşenini görüyor olacağız. Bu bileşen yardımı ile herhangi bir adımdan sonra uygulamamıza ya da tasarladığımız akış esnasında birden fazla işlemi aynı anda yapabilmemize olanak tanıyacaktır. Bu yazımızda ilk olarak paralel activity 'i tanıyacağız. Sonrasında örnekler ile nasıl kullanabileceğimize göz attıktan sonra nelere değindiğimizi özet olarak göz attıktan sonra yazımızı tamamlamış olacağız.

Parallel Activity 'ler iki ya da daha fazla Sequence Activity 'lerden oluşmaktadır. Bu aktivite bileşeni birden fazla sequence activity 'i ve içerisinde yapılmış olan işlemlerin teorik olarak aynı anda başlamasını planlamaktadır. Ancak teorik olarak yer olan bütün sequence activity lerin aynı anda başlayacağı söylense de gerçekte böyle bir durum oluşmaz. Belirsiz bir rastgelelik ile birbirilerini takip ederek gerçekleşmektedir. Yani a aktivitesi tamamlandıktan sonra b aktivitesi başlar ve sonrasında yeniden a aktivitesinin başlayabileceği gibi b aktivitesi de başlayıp tamamlanabilir. Ancak bu rastgelelik iki işleminde sorunsuzca gerçekleşmesini ve tamamlanmasında herhangi bir engel taşımamaktadır. İşlemin en sonunda her iki aktiviteninde sorunsuzca tamamlandığı gözlemlenecektir.

Parallel activity 'lerin ektileyici özelliklerinden biri de dallarda yer alan sequence aktivitelerden herhangi biri Delay Activity yer alırsa, bunun bitmesi beklenmez ve bir diğer daldaki activiteye geçilir ve akışın sorunsuzca işlemesi sağlanmış olur. Bu işlemlerin bu şekilde çalışmasının en basit açıklaması ise bizim hazırlamış olduğumuz uygulamaların işletim sistemleri üzerinde çalışıyor olması ve işletim sistemi de üzerinde çalışan işlemleri thread 'ler ile işletmesinden kaynaklanmaktadır. Thread 'lerde birbirlerinin tamamlanmasını beklemek yerine herhangi bir rastgelelik ile çalışmasından ötürü uygulamanın beklemesi ya da herhangi bir sebepten ötürü bozulması durumunda sırada bekleyen diğer iş parçacığına geçerek işlemi devam ettiriyor olmasıdır.

Delay Activity, iş akışını belirli bir süre duraklamasını ve sonrasında da çıkmasına olanak tanımaktadır. TimeoutDuration ve TimeSpan özelliklerini kullanılır.

Parallel Activity sınıfı System.Workflow.Activities isim alanı altında yer almaktadır. Parallel aktiviteleren sık olarak while döngüsünün kullanılması gereken durumlarda görülmektedir.

Genel olarak paralel actviteyi tanıdığımıza göre artık örneklere geçiş yapabiliriz. Bu yazımızda geliştireceğimiz örneği Visual Studio 2010 RC1 sürümünde geliştiriyor olacağız. Ancak .Net Framework 3.0 sürümünü kullanacağımız için Visual Studio 2008 ya da gerekli eklentileri yüklenmiş 2005 sürümünde de sorunsuzca geliştirilebilir.

Projemizi Workflow seçeneği altında yer alan Sequential Workflow Console Application proje şablonu üzerinde geliştiriyor olacağız. Proje oluştulduğunda karşımıza Sequential Workflow tasarım ekranı gelecektir.


Örneğimizi paralel atvitileer ile yapacağımız için bir adet bu aktivite tipinden tasarım ekranına sürükleyoruz.



Göreceğiniz üzere paralel aktiviteyi tasarım ekranına eklediğimizde iki tane sequence acticity 'nin eklendiğini göreceğiz. Peki iki değilde daha fazla akışı aynı anda çalıştırmak istediğimizde nasıl bir yol izlememiz gerekmektedir. Bunun için paralel aktivite üzerinde sağ tıklama yaptıktan sonra açılan menüden Add Branch seçeneğine tıklamamız yeterli olacaktır. Bu işlem sonrasında artık karşımızda aynı anda çalıştıracağımız üç adet akış olacaktır. Bu işlemi tekrarlayarak ihtiyacımız kadar akış ekleyebilmemiz mümkündür.



Ayrıca paralel aktiviteler içerisinde de akışın iptal olması ya da bozulması durumunda yapılacak işlemler için gerekli özellikler yer almaktadır.

Şimdi uygulama geliştirmek için gerekli olan bileşenleri ekliyoruz ve tasarım ekranında geliştirmiş olduğumuz akış aşağıdaki görünüme kavuşuyor.


Şimdi ise eklemiş olduğumuz CodeActivity lerin arka plan kodlarını yazarak işlemlerimize devam ediyoruz.

using System;

using System.Workflow.Activities;

namespace ParallelActivity
{
    public sealed partial class Workflow1 : SequentialWorkflowActivity
    {
        public Workflow1()
        {
            InitializeComponent();
        }

        private void codeActivity1_ExecuteCode(object sender, EventArgs e)
        {
            Console.WriteLine("Sol taraf çalıştı.");
            solTarafSay++;
        }

        private void codeActivity2_ExecuteCode(object sender, EventArgs e)
        {
            Console.WriteLine("Sag taraf çalıştı.");
            sagTarafSay++;
        }

        private int solTarafSay;
        private int sagTarafSay;
    }
}

Ayrıca while döngüleri içerisinde kullanacak olduğumuz özellikleri de tanımladık. Sonrasında while bileşenin üzerinde sağ tıkladıktan sonra özelliklerinden condition değerine System.Workflow.Activities.Rules.RuleConditionReference değerini atıyoruz. Condition özelliğine ise aşağıda belirtiğimiz şekilde tanımlıyoruz.



Hem sol tarafı hem de  sağ tarafı tanımladıktan sonra while döngülerinin özelliklerinde yer alan condition seçeneğine baktığımızda aşağıdaki görünüme benzer bir hal alması gerekmektedir.



SoSon olarak aktivitenin dallarına delay activity eklerek bekleme durumunda nasıl bir işlem yapacağını gözlemleyeceğiz. Ayrıca tamamlandığını belirtmesi için akışın en sonuna bir tane daha kod aktivitesi ekliyoruz ve geliştirme işlemini tamamlıyoruz.



Sol taraftaki bekleme değerini bir saniye, sağ taraftaki bekeleme değerini iki saniye olarak verdiğimizi hatıralatarak hazırlamış akışı çalıştırıyoruz.



Oluşan program çıktısından da göreceğiniz üzere paralel aktivite bizim belirtmiş olduğumuz bekleme sürelerinin aksine ilk başta sıra ile çalışmasının aksine rastgelelik ile çalıştığını da bu sayede gözlemlemiş oluyoruz.

Sonuç olarak yazımızı toparlamak gerekirse, paralel aktivitelerin birden fazla iş akışını çalıştırabildiğini ve bu akışları aynı anda değil thread lere bağlı olarak rastgele bir sıradanlıkla çalıştırdığını öğrendik. Sonrasında hazırlamış olduğumuz örnek yardımı ile bu anlattış olduğumuz bilgileri doğrulyarak yazımızı tamamladık. Bir sonraki WWF yazımızda Condition kavramına değiniyor olacağız.

Umarım yararlı olabilmiştir.

Turhal Temizer
info@turhaltemizer.com

Salı, Şubat 02, 2010

WF - Parametre Kullanımı

Windows Workflow (WF) teknolojisini şu ana kadar temel uygulama tipleri ve istisnai durumlar (Exceptions) konularını inceledik. WF ile uygulama geliştirirken hangi adımlara dikkat etmemiz gerektiği ve kafamıza takılan geliştirme işlemlerini nasıl yapabileceğimizi detaylı bir şekilde inceleyerek yazılarımıza devam ediyor olacağız. Bu sefer ise WF 'da parametre kullanılmasını inceliyor olacağız.

Son kullanıcının kullanımına açılacak uygulamalar çok büyük oranda istek cevap mantığına göre çalışmaktadır. Bu istekleri taşıyabilmek için ise uygulamalarda parametrelerden yararlanılmaktadır. Bu parametreler hem uygulama içerisinden herhangi bir değerden gelirken dış veri giriş ya da istek controlleri yardımı ile de kullanılabilmektedir. Özellikle portal sistemlerinde iş akışı kullanımı çok yoğundur ve gönderilen parametreler doğrultusunda izin talepleri, araç istekleri, döküman paylaşımları ve akla gelmeyen diğer iş akışlarının hazırlanmasında parametre kullanımı çok ama çok fazladır. Bu sebepten ötüdür ki bu konu WF teknolojisi ile uygulama geliştiren geliştiriciler de çok önceliklidir.

Şimdi biz bu işlemleri WF teknolojisi üzerinde nasıl kullanabilceeğimizi incelemeye başlayalım. Visual Studio 2010 (VS2008 ya da WF eklentileri yüklenmiş VS2005 'te olabilir. Aynı özellikler her ikisinde de geçerlidir.) üzerinde Workflow seçeneği seçili iken .Net Framework 3.0 sürümü altında yer alan Sequential Workflow Console Application proje şablonunu seçiyor ve ismini ParameterParsing vererek  projeyi oluşturuyoruz. Sonrasında karşımıza alışık olduğumuz WF tasarım ekranı ve bileşenlerimiz gelecektir.

Tasarım ekranı üzerine Code Activity bileşenini sürüklüyor ve ExecuteCode olayınına parametre alabilmesi için gerekli işlemleri uygulamaya başlıyoruz.


Sonrasında kod tarafına basit bir string özellik oluşturup codeActivity bileşeninin içerisinde kullanılmak üzere ekliyoruz.

private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
    Console.WriteLine("Bulunan string değer: [{0}]",StringToPrint);
}

private string _stringToPrint;

public string StringToPrint
{
    get { return _stringToPrint; }
    set { _stringToPrint = value; }
}

Eklemiş olunan CodeActivity bileşeni üzerinde parametre kullanılması için gerekli hazırlıklar tamamlandı. Peki, parametreler nereden gelecek? Bu örneğimiz için Program.cs içerisinde yer alan WorkflowRuntime.CreateWorkflow metodunun içerisine Dictionary<> olarak bir parametre daha vereceğiz. Bu parametre bizim hazırlamış olduğumuz Workflow tasarım ekranını hazırlarken belirlemiş olduğumuz özelliklerin isimlerini ve alacakları değerleri vermemiz durumunda onlar global olarak değişkenleri kabul edecek ve gerekli değerleri tanımlayacaktır.

Yukarıda belirttiğimiz şekilde Program.cs dosyasının içerisini düzenledikten sonraki son görünüm aşağıdaki gibi olacaktır.

using System;
using System.Collections.Generic;

using System.Threading;
using System.Workflow.Runtime;

namespace ParameterParsing
{
    class Program
    {
        static void Main(string[] args)
        {
            using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
            {
                AutoResetEvent waitHandle = new AutoResetEvent(false);
                workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) { waitHandle.Set(); };
                workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
               {
                   Console.WriteLine(e.Exception.Message);
                   waitHandle.Set();
               };
               Dictionary<string, object> parameters = new Dictionary<string, object>();
                    parameters.Add("StringToPrint", "Parametreleri kullanarak sonuçları elde ettik...");
               WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(ParameterParsing.Workflow1),parameters);
               instance.Start();

               waitHandle.WaitOne();
            }
        }
    }
}

Workflow1.cs dosyasına eklemiş olduğumuz StringToPrint özelliğini program.cs dosyasında bir koleksiyonun içerisinde tanımladıktan sonra iş akışı başladığında çağırılacak parametrelerin arasında olması için intance 'ın parametreleri arasına ekledikten sonra işlemimizi tamamlamış oluyoruz.

Yapmış olduğumuz işlemler sonrasında uygulamamızı çalıştırdığımızda karşımıza aşağıdaki gibi bir ekran çıktısı çıkacaktır.



Daha önce de bahsettiğimiz gibi WorkflowInstance 'a atayacağımız değeleri CreateWorkflow metodunun sonucunda dönecek olanlardan elde ediyorduk. Bu metotta birden fazla aşırı yüklemeden oluşmaktadır. Bunlardan biri de kolleksiyonla birlikte işlem yapandır. Biz de bu metottan yararlanarak oluşturmuş olduğumuz Dictionary koleksiyonunu ekleyerek işlemimizi yaptık.

Şimdi örneğimizi biraz daha karmaşıklaştırarak parametre kullanımını incelemeye devam edelim. Bu sefer bir kullanıcı sınıfı oluşturalım. Sonrasında bu sınıfın içerisine Adı ve Soyadı diye iki adet eleman tanımlayalım. Sonrasında ise oluşturmuş olduğumuz bu sınıfın içerisinde yer alan elemanları Workflow tasarım ekranı üzerinde eklemiş olduğumuz CodeActivity bileşeninin çalışma esnasında görüntülenecek şekilde hazırlayalım.

Eklemiş olduğumuz işlem sonrasında Workflow1.cs 'nin içeriği aşağıdaki gibi olacaktır.

using System;
using System.Workflow.Activities;
using System.Collections.Generic;

namespace ParameterParsing
{
    public class Kullanici
    {
        public Kullanici(string ad, string soyAd)
        {
            this.adi = ad;
            this.soyAdi = soyAd;
        }

        private string adi;

        public string Adi
        {
            get { return adi; }
            set { adi = value; }
        }
        private string soyAdi;

        public string SoyAdi
        {
            get { return soyAdi; }
            set { soyAdi = value; }
        }
    }

    public sealed partial class Workflow1 : SequentialWorkflowActivity
    {
        public Workflow1()
        {
            InitializeComponent();
        }

        private void codeActivity1_ExecuteCode(object sender, EventArgs e)
        {
            foreach (Kullanici k in Insan)
            {
                Console.WriteLine("İsminiz [{0},{1}] 'dir.", k.Adi, k.SoyAdi);
            }
        }

        private List<Kullanici> insan;

        public List<Kullanici> Insan
        {
            get { return insan; }
            set { insan = value; }
        }
    }
}

Kod parçasını yukarıdaki şekilde oluşturduk ve iş akışının çalışması esnasında oluşacak işlemleri de hazırladık. Şimdi program.cs üzerinden gerekli parametreleri oluşturabiliriz.

using System;
using System.Collections.Generic;

using System.Threading;
using System.Workflow.Runtime;

namespace ParameterParsing
{
    class Program
    {
        static void Main(string[] args)
        {
            using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
            {
                AutoResetEvent waitHandle = new AutoResetEvent(false);
                workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) { waitHandle.Set(); };
                workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
               {
                   Console.WriteLine(e.Exception.Message);
                   waitHandle.Set();
               };
               Dictionary<string, object> parameters = new Dictionary<string, object>();
                    List<Kullanici> insan = new List<Kullanici>();
                    insan.Add(new Kullanici("Tur", "Tem"));
                    insan.Add(new Kullanici("Ser", "Tur"));

                    parameters.Add("Insan", insan);
               WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(ParameterParsing.Workflow1),parameters);
               instance.Start();

               waitHandle.WaitOne();
            }
        }
    }
}


Oluşturulan sınıfa ait varlıklara değerleri atadık ve sonrasında uygulamayı çalıştırdığımızda bu değerleri sorunsuzca göreceğiz.



Bir önceki örneğimizde string bir değeri tutan bir parametreyi akış bileşenin nasıl kullanacağımızı gördük. Bu örneğimizde de Oluşturduğumuz bir sınıfı (Veri tabanı tablosu gibi de düşünebilirsiniz) içerisinde yer alan varlıklardan yararlanarak buna değerler atadık ve yine codeactivity bileşenin içerisinde sorunsuzca gösterebildik.

Sonuç olarak Workflow Foundation ile geliştirilen uygulamlarda parametreleri el ile atayıp kullanabileceğimiz gibi bir veri topluluğu içerisinde de çekip kullanabiliriz. Ayrıca bu parametreleri kullanabilmemiz için program.cs sınıfının içerisinde CreateWorkflow metoduna parametre olarak  generic tipten bir parametre ekleyerek parametrelerin kullanılmasına olanak tanıyabiliriz.

Bir sonraki yazımızda Workflow Foundation ' da Paralel Aktiviteleri inceliyor olacağız.

Umarım yararlı olabilmiştir.

Turhal Temizer

info@turhaltemizer.com
turhal.temizer@csharpnedir.com

Cuma, Ocak 22, 2010

WF - Exception İşlemleri

Günümüzde iş akışı teknolojilerini sayar mısınız şeklinde bir soru geldiğinde bu çözümün Microsoft kanadında ki ürünü olarak aklımıza ilk olarak Windows Workflow Foundation çözümü gelmektedir. Özellikle insanlar tarafından tetiklenen (Human Workflow) iş akışı yapıları arasında çok kullanışlı bir teknoloji olarak bulunmaktadır.

Workflow Foundation teknolojisi incelemeye hem kod yardımı ile hem de tasarım ekranı üzerinden yapmış olduğumuz basit bir uygulama ile başlamıştık. Bu yazı dizimizde ki ana amaç iş akışı ile ilgili uygulama geliştirmek istediğimizde nasıl aklımızda nasıl yapacağız şeklinde bir soru işareti kalmadan rahatlıkla yapmaktadır.

Geliştirilen bütün uygulama tiplerinde ortaya çıkan istinai durumları (Exception) tespit edip kontrol ediyor olabilmek en önemli özelliklerden birisidir. Bu yazımızda Workflow uygulamalarında istisnaları nasıl kontrol edebileceğimizi incelemeye çalışıyor olacağız.

WF 'te Exception kavramını örnek üzerinden incelersek çok daha akılda kalıcı olacaktır. Örneği, Visual Studio 2010 Beta 2 IDE 'sinde .Net Framework 3.0 sürümü üzerinde geliştiriyor olacağız. Peki, neden .Net 4.0 dururken 3.0 üzerinde geliştiriyoruz. Sharepoint uygulamaları (2010 sürümü dahil olmak üzere), daha önceden geliştirilen uygulamaları  ve .Net 3.0 ile geliştirilecek olan yeni uygulamaları göz önünde tutarak bu teknoloji üzerinde inceliyoruz.

Uygulamamız için proje şablonlarından Workflow seçeneğini ve Framework sürümü olarakta .Net 3.0 'ı seçtikten sonra Sequential Workflow Console Application 'ı seçerek çalışmaya başlayabiliriz.



Exception örneğini basitçe inceleyebilmek için karşımıza çıkan dizayn ekranına Code Activity bileşeni ekliyoruz.



Sonrasında eklemiş olduğumuz kontrolün üzerine sağ tıklama yaptıktan sonra properties ekranından events (olaylar) seçeneğinden ExecuteCode seçeneğine çift tıklayarak arka plana kod oluşturuyor ve aşağıdaki basit kod parçasını ekliyoruz.



private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
    throw new ApplicationException("Başarısız oldu...");
}

Code Activity kontrolünün çalıştığı anda çalışacak olan olayına uygulamanın istisnai duruma düşmesi için gerekli kod parçasını ekliyoruz. Bir önceki yazımızdan da hatırlayacağınız üzere WorkflowRuntime sınıfının altında yer alan WorkflowTerminated özelliğinden düşen istisnai durumları görüntüleyebilmemiz mümkündür. Eğer ki uygulamayı çalıştırır ve olayı bulunduğu delegate 'in içerisinde yer alan kod parçasının içerine breakpoint eklememiz durumunda debug anında düştüğünü ve bizim eklemiş olduğumuz mesajın yazıldığını göreceğiz.



Basit anlamda ilk istisna yakalanması işlemini sağladık. Hata durumlarını daha spesifik yakayabilmemiz için workflow ortamında iki adet daha exception tipi bulunmaktadur. Bunlar Cancel Handler ve Fault Handler 'dır.


Bizim şimdi değineceğimiz bölüm ise View Fault Handlers olacaktır. İşlemin sonuçlanamadığı durumlar için bu bölüm kullanılmakta ve istisnaları yakalamak için Fault Handler bileşeni kullanılmaktadır.



Bu bileşeni Fault Handlers bölümüne sürükledikten sonra karşımıza çıkan ekranın üzerine sağ tıklama yaptıktan sonra properties ekranına geliyor ve FaultType 'a biraz önce CodeActivity içerisinde kullanmış olduğumuz ApplicationException sınfını bularak seçiyoruz.

Not: Bu tip mscorlib 'in içerisinde yer alan System isim alanında yer alır.



Sonrasında view fault handlers ekranında eklemiş olduğumuz FaultHandler bileşeninin içerisine Code Activity sürükledikten sonra properties ekranından ExecuteCode olayına istediğimiz hata mesajını yazdırıyoruz.

 
Eklemiş olduğumuz kod parçası aşağıdaki gibi olacaktır.

private void codeActivity2_ExecuteCode(object sender, EventArgs e)
{
    Console.WriteLine("Olamaz... Yakaladın beni.");
    Console.ReadLine();
}

Daha sonra uygulamayı derleyip debug modda çalıştırdığımızda iş akışı içerisine eklemiş olduğumuz code activity 'de ilk olarak hataya düşecek ve sonrasında da faulthandler içerisine düşücektir.



Düşündüğümüz senaryolar sorunsuzca çalışıyor. Şimdi ise iş akışı tasarım ekranına Sequence ekliyoruz ve daha önce oluşturmuş olduğumuz codeActivity1 isimli kontrolü bu bileşenin içerisine ekliyoruz.


Sonrasında daha önce fault handlers durumunda yapmış olduğumuz işlemlerin hepsini tekrarlayarak aşağıdaki durumu sağlıyoruz.


Sonradan eklemiş olduğumuz sequence 'in içerisine eklemiş olduğumuz FaultHandler bileşeninin içerisine düşen istisnai durumları artık gözlemleyebiliriz. Projemizi derledikten ve hatasız olduğunu anladıktan sonra debug mod ile çalıştırdıktan sonra sequence içerisine eklemiş olduğumuz hata bilgisine geldiğini ve bu mesajı gösterdiğini gözlemleyeceğiz.


Ayrıca uygulama çalıştırılırken gözlemleneceği gibi ilk olarak en iç tarafta yer alan yerel iş akışları tamamlanmakta ve sonrasında dış akışlara geçilmektedir. Bu mantıktan ötürüde en son eklediğimiz sequnce bileşeninin içerisinde bulunan FaultHandler 'a girecek ve akışı burada kesecektir. Bu sayede iç kontroller esnasında eğer ki akışta bir problem çıkarsa akışı durdurup hata mesajını en son adımı beklemeden verdirebilme olanağımız olacaktır.

Hazırlanmış olan proje çalışırken herhangi bir aksaklık (Fault) ortaya çıkması durumunda istediğimiz mesajları gösterebileceğimizi gördük. Ancak daha önceden de değindiğimiz gibi uygulama esnasında ortaya çıkan sorunlar ApplicationException sınıfında tutulmaktadır. Bu sebepten ötürü iş akış diyagramına eklemiş olduğumuz FaultHandler bileşeninin özellikler kısmında yer alan Fault kısmını kullanarak belirtmiş olduğumuz hata mesajını verdiyor olacağız. Hatırlayacağınız üzere yazımıza ilk başladığımızda ApplicationException sınıfını kullanmış,  WorkflowRuntime sınıfının workflowTerminated olayını tetiklemiş ve oluşan uygulama aksaklıklarında "Başarısız oldu..." mesajını verdirmiştik. Bu durumu şimdi FaultHandler bileşenini eklemiş olduğumuz yerlerde nasıl kullanacağımıza göz atalım.

FaultHandler bileşenin üzerinde sağ tıklama yaptıktan sonra karşımıza çıkan ekrandaki özelliklerden Fault özelliğine değeri atayacağız.

Bu değer için ApplicationException sınıfında bir özellik (property) tanımlayıp kullanıyor olacağız.

private ApplicationException myException;

public ApplicationException MyException
{
    get { return myException; }
    set { myException = value; }
}

Özelliği tanımladıktan sonra biraz önce göstermiş olduğumuz yere yol olarak MyException özelliğini veriyoruz.



Artık uygulamamızı çalıştırıp hata mesajımızı olabilirim. Debug modda çalıştırdığımız karşımıza çıkan durum tam istediğimiz gibi olacaktır. Daha önceden MyException sınıfını kullanarak belirttiğimiz hata mesajını belirttiğimiz her yerde görebilme olanağımız vardır.


Gözlemlediğimiz üzere istediğimiz mesaj değer olarak karşımıza çıkmıştır.

Şimdi yapacağımız işlemde ise Sequence içerisinde yer alan codeActivity 1 'i silmek ve yerine Throw bilşenini eklemek olacaktır. Bu sayede proje çalışırken karşılaşılan herhangi bir istisnai durumda fırlatılan hatayı kontrol etmiş ve istediğimiz mesajı verebilmiş olacağız.

Throw bileşeninde kullanılmak üzere ApplicationException sınfından yararlanılarak bir özellik oluşturuyoruz.

public ApplicationException ExceptionToThrow
{
    get { return (new ApplicationException("Pardon!")); }
}


Throw bilşeninde özelliği aşağıdaki gibi kullanabiliriz.


ThrowActivity bileşenine sağ tıklama yaptıktan sonra Fault özelliğine daha önceden tanımlamış olduğumuz özelliği atıyoruz.



Bu işlem sonrasında artık projemizi oluşturup hazırlanan property 'ler yardımı throw bilşenini kontrol edebiliriz. Debug ile breakpoint noktasına geldikten sonra MyException.Message 'dan dönecek olan değere ExceptionToThrow a atamış olduğumuz değeri görürüz.


Görüldüğü üzere istediğimiz hata mesajını göstermiş oluyoruz.

Bu örnek ile geldik bir yazımızın daha sonuna, bu yazımızda Windows Workflow Foundation 3.0 ile Exception kavramını detaylı bir şekilde incelemeye çalıştık. Hem kod yardımı ile hemde gerekli WF bileşenlerinin kullanarak nasıl kullanabileceğimize değinmiş olduk.

Umarım yararlı olabilmiştir.

Turhal Temizer

info@turhaltemizer.com
turhal.temizer@csharpnedir.com