https://buraksenyurt.com/Burak Selim Şenyurt - WF 4.0 Beta 22010-02-01T07:22:36+00:00Matematik Mühendisi Bir Bilgisayar Programcısının NotlarıBurak Selim SenyurtBlogEngine.Net Syndication Generatorhttps://buraksenyurt.com/opml.axdBurak Selim SenyurtMatematik Mühendisi Bir Bilgisayar Programcısının Notlarıtr-TRBurak Selim Şenyurt0.0000000.000000https://buraksenyurt.com/post/Correlation-Nedir-Beta-2Correlation Nedir? Yenir mi? İçilir mi?2010-02-01T00:25:00+00:00bsenyurt<p><img style="float: right;" src="/pics/2010%2f1%2fblg126_Giris.jpg" alt="" />Merhaba Arkadaşlar,</p>
<p>Bazen bir kavramı yada konuyu anlamakta inanılmaz zorlandığınızı hatırlayın. Ne yaparsınız? Kimisi kendisini yemeğe verir. Kimisi hayat küsermişçesine bir köşeye çekilir. Kimisi kendiyle baş başa kalır ve çığlık çığlık haykırır. Kimisi de daha akıllı davranıp bir süre tatile çıkar veya anlayamadığı kavramla ilişkili herhangibir dökümanı bir süreliğine araştırmamaya, okumamaya karar verir. Neredeyse unuturcasına bir zaman koyar araya. Sonrasında ise aynı konuyu tekrar araştırmaya karar verir. İnanın başarılı olma şansı bir önceki denemeye göre çok daha yüksek olacaktır. Önemli olan noktalardan birisi, yılmadan bu iterasyona devam edebilmektir. Okudunuz, hala anlamadınız...Kısa bir ara daha...Sonra tekrar aynı konu ama mümkünse farklı kaynaklarla...<img title="Wink" src="/editors/tiny_mce3/plugins/emotions/img/smiley-wink.gif" alt="Wink" border="0" /></p>
<p>Bende bir süredir<strong> Workflow Service'</strong> lerde oldukça önemli olan konulardan birisi üzerinde araştırmalarımı tamamen durdurmuştum. <strong>Correlation</strong>. Çünkü; <strong>Matematikte "bağlılaşım/korelasyon"</strong>, <strong>ekonomide "bağlanım"</strong>, <strong>nükleer bilimlerde "bağlantı/eş ilişki"</strong>, <strong>denizbilimde "kaçınım"</strong>, <strong>tıpta "Aferent uyarıların gerekli cevabı oluşturmak üzere beyinin ilgili merkezinde birleşmesi" </strong>olarak çevirileri yer alan bu kavramın, <strong>Workflow Services</strong> içerisinde ne anlama geldiğini anlamak için epey bir süre tepinmem gerekmişti. Geçtiğimiz günlerde aynı konu üzerinde yeniden durmaya ve araştırmaya ve edindiğim bilgileri sizlere paylaşmaya karar verdim. İşte elde ettiğim sonuçlar;</p>
<p><strong>Correlation </strong>kavramını mesajları bir arada gruplamanın bir yolu olarak düşünülebilir ilk etapta. Örneğin bir<strong> talep(Request)</strong> ve bu talebe karşılık gönderilen <strong>cevap(Reply) </strong>arasındaki ilişki <strong>Correlation </strong>olarak ifade edilmektedir. Özellikle <strong>WCF(Windows Communication Foundation)</strong> tarafında <strong>Session </strong>bazlı haberleşmelerde mesajlar arasında bir <strong>Correlation </strong>oluştuğu söylenebilir. Ancak <strong>Correlation' </strong>ın farklı bir yönü daha vardır. Bir <strong>servis örneği(Instance) </strong>ile bir <strong>oturum(Session)</strong> arasında da bağıntı kurulabilir. Yani bir <strong>SessionId</strong> değerine ait olaraktan hareket eden mesajların içeriğinde yer alan bazı veri parçalarının, <strong>Session</strong> ile alakalı bir servis örneği ile eşleştirilmesi mümkün olabilir. Bir başka deyişle aynı <strong>SessionId</strong> değeri altındaki mesajların her zaman için aynı servis örneğine ait olduğunun anlaşılmasında, <strong>SessionID=Service Instance ID</strong> eşitliğinin sağlanması da <strong>Correlation </strong>olarak ifade edilebilir. Bu ilişki çoğunlukla <strong>bilinçsiz(Implicit)</strong> olarak sağlanır. Yani, geliştiricinin çoğu zaman bir aksiyonda bulunmasına gerek yoktur. Aslında bu durumu aşağıdaki şekilde olduğu gibi canlandırabiliriz.</p>
<p><img src="/pics/2010%2f1%2fblg126_Correlation.gif" alt="" /></p>
<p>Ancak <strong>Workflow</strong> örneklerinde uzun zaman süren süreçlerin ele alınması da söz konusudur<strong><em>(Long Running Process)</em></strong>. İstemcilerin, <strong>Workflow Service'</strong> ler ile olan haberleşmelerinde aradaki oturumu kapatıp ayrılmaları bu tip süreçlerde son derece yaygındır. Buna göre istemci ile servis arasındaki oturumun her an sonlanabilir olması önemli bir sorunu ortaya çıkarmaktadır; <strong>Correlation nasıl sağlanacak</strong>? <img title="Undecided" src="/editors/tiny_mce3/plugins/emotions/img/smiley-undecided.gif" alt="Undecided" border="0" /></p>
<p>Bu amaçla <strong>Workflow Service'</strong> lerde <strong>Correlation' </strong>ın sağlanması için kullanılan çeşitli teknikler mevcuttur. Aslında burada da tam bir kavram kargaşası vardır. En güvenilir kaynaklardan birisi olarak ele alacağımız <strong>MSDN</strong>, <strong>Correlation' </strong>ı <strong>Content-Based </strong>ve <strong>Protocol-Based </strong>olmak üzere iki çeşide ayırmıştır. <strong>Protocol-Based Correlation'</strong> da kendi içerisinde <strong>Context </strong>ve <strong>Request-Reply </strong>isimli iki farklı <strong>Correlation </strong>tekniğini daha barındırmaktadır.</p>
<p><strong>Content-Based Correlation'</strong> da <strong>service örneği(Instance) </strong>ile ilişkili olan veri<em>(Map edilmiş veri olaraktan da düşünebiliriz) </em>mesajın içeriğinde yer alır. Örneğin mesajın <strong>Header</strong> veya <strong>Body </strong>kısımlarında bulunabilir. Dolayısıyla <strong>Correlation' </strong>ı sağlayan arabirimlerin <strong>XML </strong>tabanlı olan bu veri içeriğini kontrol edebilmesi gerekmektedir. İşte bu noktada <strong>XPath </strong>gibi sorgu teknikleri devreye girmektedir. <strong>Protocol-Based Correlation </strong>ise iletişim mekanizmasını baz alır ve buna göre mesajlar arasında yada mesajlar ile doğru servis örneği arasında gerekli eşleştirmeyi sağlar.</p>
<p>Bu giriş yazımızda özellikle <strong>Content-Based Correlation</strong> üzerinde durabiliriz. En çok örneklenen model genellikle budur. <strong>Workflow Service' </strong>lerde servise gelen ve servisten giden mesajların içerdiği veri parçaları ile çalışma zamanındaki servis örnekleri arasında eşleştirme yapmak<em>(yani Correlation' ı sağlamak) </em>son derece kolaydır. Tüm mesajlaşma aktivitelerinin <strong>CorrelationInitializers </strong>isimli bir koleksiyonu bulunur. Bu koleksiyon içerisinde <strong>Key-</strong><strong>Query </strong>çiftleri yer almaktadır. Tahmin edileceği üzere <strong>Key </strong>değerleri ile <strong>Query' </strong>lerin birbirlerinden ayrıştırılması sağlanır. En önemli nokta ise <strong>Query' </strong>dir. <strong>Query </strong>içerisinde yer alan <strong>XPath </strong>sorgusu ile <strong>Content </strong>içerisindeki veri işaret edilir. Tabi bir mesajlaşma aktivitesi, diğer bir mesajlaşma aktivitesinin başlattığı <strong>Correlation' </strong>u takip edebilmelidir. Bunun içinde <strong>CorrelationWith </strong>isimli özellikten yararlanılır. Bu bilgilere göre <strong>Correlation' </strong>ın bir şekilde <strong>başlatılması(Initialize) </strong>ve <strong>takip edilmesi(Follow) </strong>gerektiği anlaşılmaktadır. Başlatılan bir <strong>Correlation' </strong>ın takip <span style="text-decoration: underline;">edilmemesi </span>halinde mesajlar ve servis örneği arasında bir eşleştirmenin yapılması söz konusu olmayacaktır. Elbette <strong>Workflow Foundation 4.0 </strong>içerisinde bir <strong>Correlation' </strong>ın başlatılmasını kolaylaştıran bir aktivitede gelmektedir. <strong>InitializeCorrelation </strong>bileşeni.</p>
<p>Sanırım şu ana kadar anlattıklarımız ile kafamızda <strong>Correlation'</strong> ın ne olduğuna dair bir fikir oluşmuştur. Tabi konuyu kavramak tek başına yeterli değildir. Pratiğe dökmemizde yarar vardır. Ancak şu an için bu konudaki araştırmaya ara verip tatile çıkmak niyetindeyim. Tekrardan görüşünceye dek hepinize mutlu günler dilerim.</p>2010-02-01T00:25:00+00:00wcfwcf 4.0wfwf 4.0workflow servicesbsenyurtBazen bir kavramı yada konuyu anlamakta inanılmaz zorlandığınızı hatırlayın. Ne yaparsınız? Kimisi kendisini yemeğe verir. Kimisi hayat küsermişçesine bir köşeye çekilir. Kimisi kendiyle baş başa kalır ve çığlık çığlık haykırır. Kimisi de daha akıllı davranıp bir süre tatile çıkar veya anlayamadığı kavramla ilişkili herhangibir dökümanı bir süreliğine araştırmamaya, okumamaya karar verir.https://buraksenyurt.com/pingback.axdhttps://buraksenyurt.com/post.aspx?id=b69941a7-8ad1-48f1-b562-645bd8f9789f0https://buraksenyurt.com/trackback.axd?id=b69941a7-8ad1-48f1-b562-645bd8f9789fhttps://buraksenyurt.com/post/Correlation-Nedir-Beta-2#commenthttps://buraksenyurt.com/syndication.axd?post=b69941a7-8ad1-48f1-b562-645bd8f9789fhttps://buraksenyurt.com/post/Webiner-Workflow-Foundation-40-Introduction-Beta-2Webiner - Workflow Foundation 4.0 - Introduction [Beta 2]2010-01-20T13:51:00+00:00bsenyurt<p><img style="FLOAT: left" src="http://www.buraksenyurt.com/pics/2010%2f1%2fblg134_Giris.gif" alt="" />Merhaba Arkadaşlar,</p>
<p><strong>.Net Framework 3.0</strong> sürümü ile birlikte gelen köklü yeniliklere baktığımızda <strong>Windows Presentation Foundation(WPF), Windows Communication Foundation(WCF) </strong>ve <strong>Workflow Foundation(WF) </strong>alt yapı modellerinin ön plana çıktıklarını görmekteyiz. Servis bazlı çözümlere yeni bir yaklaşım getiren <strong>WCF</strong>, kod akışlarının görsel olarak geliştirilebilmesini sağlayan <strong>WF </strong>ve windows programlamaya tamamen farklı bir görsellik kazandıran <strong>XAML </strong>bazlı <strong>WPF</strong>.</p>
<p><strong>.Net Framework 3.5 </strong>versiyonu yayınlandığında ise özellikle, <strong>WCF </strong>ve <strong>WF </strong>modellerinin bir birleriyle biraz daha haşır neşir olduklarını, içerisinde insan faktörü bulunan uzun süreli iş akışlarının geliştirilmesinde önemli ilerlemeler kaydedildiğini, iş akışı bazlı servislerin daha kolay yazılabildiğini gördük.</p>
<p>Gün geldi çok doğal olarak <strong>.Net Framework 4.0'</strong> ın ayak sesleri duyulmaya başlandı.<em>(Hatta 2008 yılının yaz aylarında yapılan Microsoft PDC' de duymaya başladık)</em> Bir kaç aya kadar <strong>Release</strong> sürümünün de çıkması beklenen <strong>.Net Framework 4.0 </strong>içerisinde gerek <strong>WCF</strong> gerek <strong>WF </strong>tarafında önemli yenilikler olduğunu görmekteyiz.</p>
<p>İşte bu Webinerimizde <strong>Workflow Foundation 4.0</strong> modelini incelemeye ve öne çıkan yenilikleri değerlendirmeye çalıştık. Önceki sürümde yer alan zorlukların anlatımı ile başlanan webinerimizde, kısaca <strong>Workflow Foundation 4.0</strong> ile gelen önemli yenilikler irdelenip basit bir örnek geliştirilmekte. </p>
<p><strong>NedirTV?com </strong>araclılığıyla gerçekleştirilen ve <strong>20.Ocak.2010 Çarşmaba</strong> günü saat <strong>21:00 </strong>ile <strong>22:00 </strong>arasında başlayacak olan webinere kayıt olmak için <a href="http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032439662&EventCategory=4&culture=tr-TR&CountryCode=TR">http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032439662&EventCategory=4&culture=tr-TR&CountryCode=TR</a> adresini kullanabilirsiniz.</p>
<p>Keyifli seyirler dilerim.</p>2010-01-20T13:51:00+00:00webinerwf 4.0webcastwfbsenyurthttps://buraksenyurt.com/pingback.axdhttps://buraksenyurt.com/post.aspx?id=ce3d257f-9361-461c-9891-f686cad4fcc40https://buraksenyurt.com/trackback.axd?id=ce3d257f-9361-461c-9891-f686cad4fcc4https://buraksenyurt.com/post/Webiner-Workflow-Foundation-40-Introduction-Beta-2#commenthttps://buraksenyurt.com/syndication.axd?post=ce3d257f-9361-461c-9891-f686cad4fcc4https://buraksenyurt.com/post/Workflow-Foundation-40-Transaction-Flow-Beta-2Workflow Services 4.0 - Transaction Flow [Beta 2]2010-01-20T01:00:00+00:00bsenyurt<p><img style="float: right;" src="/pics/2009%2f12%2fblg123_Giris.jpg" alt="" />Merhaba Arkadaşlar,</p>
<p>Geçen gece ilginç bir rüya gördüm. Bir su birikintisine damlacıklar düşüyordu. Önceleri yavaş yavaş ve uzun aralıklarla düşen damlalar söz konusuydu. Zaman ilerledikçe her bir damlanın suya değdiği noktada bir isim bıraktığını görmeye başladım.<strong> int i, for, if</strong> derken damlalar hızlanmaya başladı. Daha sık daha çok damla düşüyordu. Bazıları kocaman boyutlardaydı ve düştükleri su birikintisinde neredeyse fırtına koparıyorlardı.<strong> .Net, C#, parallel, WPF, Ajax, ASP.Net, WCF, WF</strong> derken damlaların artık nerelerden geldiğini takip edemez olmaya başladım. Ama damlalar iz bırakmaya devam ediyordu. <strong>1.1, 2.0, 3.5, 4.0, Beta, RC, RTM</strong>...derken terler içerisinde uyanmıştım <img title="Wink" src="/editors/tiny_mce3/plugins/emotions/img/smiley-wink.gif" alt="Wink" border="0" /></p>
<p>Bir kaç ay içerisinde eğer büyük bir aksilik olmassa <strong>.Net Framework 4.0 </strong>ve <strong>Visual Studio 2010</strong> ürünlerinin son sürümleri yayınlanmış olacak. Şu anda gelişmeleri <strong>Beta 2</strong> sürümü üzerinden takip etmekteyiz. Ancak yakında <strong>RC</strong> ve sonrasında <strong>RTM</strong> sürümlerininde çıkacağını ve önemli iyileştirmeler olacağını biliyoruz. Yinede gelebilecek yenilikleri takip etmek adına araştırmalarıma devam etmekteyim. Bir süredir <strong>Workflow Foundation 4.0</strong> üzerine araştırma yapmıyordum. Geçtiğimiz günlerde <strong>Transaction</strong> yönetimi ile ilişkili olarak önemli bir açığın kapatıldığını öğrendim. Buna göre<strong> Workflow Foundation 4.0</strong> öncesinde,<strong> Workflow Service'</strong> lerde istemci tarafından başlatılan <strong>Transaction'</strong> ların, servis tarafına akması mümkün olmuyordu. Şimdi bir dakika...<strong>Transaction, Flow</strong>, <strong>İstemciden Sunucuya</strong>...Ihmmmm <img title="Sealed" src="/editors/tiny_mce3/plugins/emotions/img/smiley-sealed.gif" alt="Sealed" border="0" /> Biraz kafamız karışmış olabilir. Başlamadan önce bu konu hakkında biraz bilgi vermeye çalışalım dilerseniz.</p>
<p>Bildiğiniz üzere bir <strong>Transaction</strong> içerisinde baştan sona başarılı bir şekilde tamamlanması beklenen işlemler bütünü yer alır. <strong>Transaction</strong> başlatıldıktan sonra içerisinde ceyran eden işlemlerin kalıcı olarak kabul görmesi, ancak tüm adımlardaki işlemlerin başarılı olmasına bağlıdır. Herhangibir adımda bir hata oluştuğunda <strong>Transaction'</strong> a dahil olan herkesin, <strong>Transaction</strong> başlamadan önceki <strong>durumlarına(State)</strong> dönebilmesi gerekir. Üstelik bu <strong>geri dönüşlerde(Rollback)</strong> verilerin tutarlılığını korumak önemlidir. Hatta <strong>Transaction</strong> başarılı bir şekilde sonuçlandırıldığında, çıkan verilerin de anlamlı olması beklenir. Kısaca size <strong>ACID(Atomicity,Consistensy,Isolation,Durability) </strong>kavramını aktarmaya çalıştım. Tabi zaman ilerledikçe bir <strong>Transaction'</strong> ın sadece tek bir program alanı içerisinde değil, birden fazla program alanı içerisinde ele alınmasının gerektiği durumlar oluşmuştur. Bu noktada <strong>Dağıtık Transaction(Distributed Transaction) </strong>kavramına geçilmektedir. Buna göre bir program alanı içerisinde başlatılan <strong>Transaction</strong>, başka bir program alanı içerisinde de ele alınabilir. Elbette bu tip bir senaryoda, program alanlarının farklı makineler üzerinde konuşlandırılmış olması da kuvvetle muhtemeldir. İşte bu gibi durumlarda <strong>Transaction'</strong> ın koordinasyonu için genellikle 3ncü parti araçların devreye girdiği görülmektedir<strong>(Distributed Transaction Coordinator vb...)</strong></p>
<p>Gel gelelim zaman içerisinde söz konusu <strong>Transaction'</strong> ların servisler üzerinden akması ihtiyacı doğmuştur. Buna göre bir servis tarafından başlatılan bir <strong>Transaction'</strong> a, diğer bir serviste başlatılan operasyonun da dahil olması gerekebilir. Bu durumda ilgili servis operasyonlarının tamamının aynı<strong> Transaction Scope</strong> içerisinde ele alınması gerekmektedir. <strong>Transaction Scope</strong> denilince aklıma gelen ilk şey ise <strong>Ado.Net 2.0</strong> ile birlikte gelen <strong>TransactionScope</strong> tipidir. Bu tip sayesinde, blok içerisine dahil olan farklı <strong>bağlantılar(Connection)</strong> için aynı <strong>Transaction Scope'</strong> un oluşturulması ve yönetilmesi son derece kolaylaşmıştır.</p>
<p>Şimdi gelelim bu güne. Artık elimizin altında bir <strong>Workflow'</strong> un servis bazlı olarak sunulabilmesi imkanı bulunmakta. Uzun süredir. Buna göre istemcilerin, söz konusu <strong>Workflow'</strong> ları servis bazlı olaraktan talep edebilmesi mümkün. Hal böyle olunca istemci tarafından başlatılacak bir <strong>Transaction'</strong> ın, çağrıda bulunulan <strong>Workflow Service</strong> tarafından' da ele alınabiliyor olması istenen bir özelliktir. Dolayısıyla istemcide açılan <strong>Transaction'</strong> ın <strong>Workflow Service</strong> tarafına <strong>akabiliyor(Flow) </strong>olması gerekmektedir.</p>
<p><strong>Workflow Foundation 4.0 Beta 2</strong> sürümünde söz konusu işlevselliği sağlamak için <strong>Messaging</strong> kontrollerinde yer alan <strong>TransactedReceiveScope</strong> isimli aktivite bileşeninden yararlanılmaktadır. Bu bileşen içerisinde istemcilerin çağrıda bulunacağı operasyon bildirimi yer alır. Bunun içinde <strong>Receive</strong> aktivite bileşeninden yararlanılmaktadır. Dilerseniz olayı kavramak için basit bir örnek geliştirelim. Örneğimizde aşağıdaki <strong>XAML</strong> içeriğine sahip bir <strong>Workflow Service</strong> oluşturduğumuzu göz önüne alalım.</p>
<p><img src="/pics/2009%2f12%2fblg123_Flow.gif" alt="" /></p>
<p><strong>Xaml içeriğimiz;<em>(Sadece Sequence içeriği belirtilmiştir)</em></strong></p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><p:Sequence DisplayName="Sequential Service" sad:XamlDebuggerXmlReader.FileName="G:\Projects\Workflow Foundation\Transactions\TransactionFlow\MathFlowService.xamlx" sap:VirtualizedContainerService.HintSize="325,797">
<p:Sequence.Variables>
<p:Variable x:TypeArguments="CorrelationHandle" Name="handle" />
<p:Variable x:TypeArguments="x:Int32" Name="XValue" />
<p:Variable x:TypeArguments="x:Int32" Name="YValue" />
<p:Variable x:TypeArguments="x:Int32" Name="SumResult" />
</p:Sequence.Variables>
<sap:WorkflowViewStateService.ViewState>
<scg3:Dictionary x:TypeArguments="x:String, x:Object">
<x:Boolean x:Key="IsExpanded">True</x:Boolean>
</scg3:Dictionary>
</sap:WorkflowViewStateService.ViewState>
<TransactedReceiveScope Request="{x:Reference __ReferenceID0}" sap:VirtualizedContainerService.HintSize="303,673">
<p:Sequence sap:VirtualizedContainerService.HintSize="277,474">
<sap:WorkflowViewStateService.ViewState>
<scg3:Dictionary x:TypeArguments="x:String, x:Object">
<x:Boolean x:Key="IsExpanded">True</x:Boolean>
</scg3:Dictionary>
</sap:WorkflowViewStateService.ViewState>
<p:InvokeMethod sap:VirtualizedContainerService.HintSize="255,127" MethodName="WriteTransactionInfo" TargetType="t:Helper" />
<p:Assign sap:VirtualizedContainerService.HintSize="255,57">
<p:Assign.To>
<p:OutArgument x:TypeArguments="x:Int32">[SumResult]</p:OutArgument>
</p:Assign.To>
<p:Assign.Value>
<p:InArgument x:TypeArguments="x:Int32">[XValue + YValue]</p:InArgument>
</p:Assign.Value>
</p:Assign>
<SendReply DisplayName="SendResponse" sap:VirtualizedContainerService.HintSize="255,86">
<SendReply.Request>
<Receive x:Name="__ReferenceID0" CanCreateInstance="True" DisplayName="ReceiveRequest" sap:VirtualizedContainerService.HintSize="277,86" OperationName="Sum" ServiceContractName="p1:IMathFlowService">
<Receive.CorrelatesOn>
<MessageQuerySet />
</Receive.CorrelatesOn>
<Receive.CorrelationInitializers>
<RequestReplyCorrelationInitializer CorrelationHandle="[handle]" />
</Receive.CorrelationInitializers>
<ReceiveParametersContent>
<p:OutArgument x:TypeArguments="x:Int32" x:Key="x">[XValue]</p:OutArgument>
<p:OutArgument x:TypeArguments="x:Int32" x:Key="y">[YValue]</p:OutArgument>
</ReceiveParametersContent>
</Receive>
</SendReply.Request>
<SendMessageContent DeclaredMessageType="x:Int32">
<p:InArgument x:TypeArguments="x:Int32">[SumResult]</p:InArgument>
</SendMessageContent>
</SendReply>
</p:Sequence>
</TransactedReceiveScope>
</p:Sequence></pre>
<p>Akışımız içerisinde birde yardımcı sınıf bulunmaktadır. <strong>Helper</strong> isimli sınıf içerisinde <strong>InvokeMethod</strong> aktivitesi tarafından çalıştırılan ve güncel <strong>Transaction</strong> ile ilişkili bilgileri dosyaya aktaran basit bir fonksiyonellik yer almaktadır.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.Text;
using System.Transactions;
using System.IO;
namespace TransactionFlow
{
public class Helper
{
public static void WriteTransactionInfo()
{
StringBuilder builder = new StringBuilder();
TransactionInformation currentTrx = Transaction.Current.TransactionInformation;
builder.AppendLine(String.Format("Oluşturulma zamanı {0}", currentTrx.CreationTime.ToString()));
builder.AppendLine(String.Format("Local Identifier değeri {0}", currentTrx.LocalIdentifier.ToString()));
builder.AppendLine(String.Format("Distributed Identifier değeri {0}", currentTrx.DistributedIdentifier.ToString()));
File.WriteAllText("c:\\TransctionInformations.txt", builder.ToString());
}
}
}</pre>
<p><strong>Workflow</strong> çok basit olarak istemciden gelen iki sayının toplamını geriye döndürmek üzerine tasarlanmıştır. Ancak dikkat edilmesi gereken nokta kullandığı <strong>Transaction</strong> bilgileridir. Tabi şu noktada unutulmamalıdır. Hem <strong>Workflow Service</strong> hemde istemci uygulama<strong> System.Transactions.dll assembly'</strong> ını referans etmelidir. Helper sınıfı içerisinde yer alan WriteTransactionInfo metodu text tabanlı bir dosya içerisine eğer varsa güncel transaction bilgilerini yazdırmaktadır. Bunlardan ilki transaction oluşturulma zamanıdır<strong>(CreationTime)</strong>. Sonrasında <strong>yerel transaction değeri(LocalIdentifier)</strong> ve <strong>dağıtık transaction değerleri(DistributedIdentifier)</strong> yazdırılır. Bu değerler <strong>GUID</strong> tipindendir.</p>
<p><strong>Workflow Service</strong> tarafında istemciden gelecek <strong>Transaction</strong> akışına izin vermek için sadece <strong>TransectedReceiveScope</strong> bileşeninin kullanılması yeterli değildir. Konfigurasyon içerisinde de transaction akışına izin verileceğinin bildirilmesi gerekir. Bu amaçla <strong>Workflow Service</strong> uygulamasındaki <strong>web.config</strong> içeriği aşağıdaki gibi düzenlenebilir.</p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding transactionFlow="true"/>
</wsHttpBinding>
</bindings>
<services>
<service name="MathFlowService">
<endpoint address="" binding="wsHttpBinding" contract="IMathFlowService"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration></pre>
<p>Dikkat edileceği üzere <strong>wsHttpBinding</strong> <strong>bağlayıcı tipi(Binding Type) </strong>için <strong>transactionFlow </strong>niteliğine <strong>true </strong>değeri atanmıştır. Bu zaten <strong>Windows Communication Foundation(WCF)</strong> tarafından bildiğimiz bir ilkedir. Şimdi gelelim istemci uygulama tarafına. <strong>Console</strong> projesi şeklinde tasarlanan istemci uygulamaya öncelikli olarak <strong>Workflow Service</strong> için gerekli proxy içeriği <strong>Add Service Reference</strong> seçeneği ile eklenmelidir. Tabi buna uygun olarak istemci tarafında üretilen <strong>app.config</strong> içerisinde de transaction akışı için gerekli bildirimler otomatik olarak üretilecektir. Bunu takiben <strong>Main</strong> metodunda aşağıdaki örnek kodların geliştirildiğini düşünelim.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.Text;
using System.Transactions;
using ClientApp.MathFlowSpace;
namespace ClientApp
{
class Program
{
static void Main(string[] args)
{
using (TransactionScope scope = new TransactionScope())
{
MathFlowServiceClient proxy = new MathFlowServiceClient();
Console.WriteLine("Çağrı öncesi Transaction bilgileri");
WriteTransactionInfo();
int? result = proxy.Sum(new Sum { x = 1, y = 4 });
Console.WriteLine("Çağrı sonrası Transaction bilgileri");
WriteTransactionInfo();
}
}
public static void WriteTransactionInfo()
{
StringBuilder builder = new StringBuilder();
TransactionInformation currentTrx = Transaction.Current.TransactionInformation;
builder.AppendLine(String.Format("Oluşturulma zamanı {0}", currentTrx.CreationTime.ToString()));
builder.AppendLine(String.Format("Local Identifier değeri {0}", currentTrx.LocalIdentifier.ToString()));
builder.AppendLine(String.Format("Distributed Identifier değeri {0}", currentTrx.DistributedIdentifier.ToString()));
Console.WriteLine(builder.ToString());
}
}
}</pre>
<p>İstemci uygulama tarafında en önemli nokta <strong>TransactionScope</strong> kullanımıdır. Ayrıca, <strong>Workflow Service </strong>operasyonunun çağırılmasından hemen önce ve sonra ortamdaki güncel <strong>Transaction</strong> bilgilerinin yazdırılması sağlanmıştır. Buna göre örnek bir çalışma zamanı çıktısı aşağıdaki gibi olacaktır.</p>
<p><img src="/pics/2009%2f12%2fblg123_Runtime.gif" alt="" /></p>
<p>Dikkat edileceği üzere istemci tarafında servis çağrısının yapılmasından sonra oluşan ve servis tarafında dosyaya yazılan <strong>Transaction</strong> bilgilerindeki <strong>DistributedIdentifier</strong> değerleri aynıdır. Bir başka deyişle istemci ve <strong>Workflow Service</strong> tarafı aynı <strong>Transaction</strong> alanı içerisinde çalıştırılmıştır. Hemen tersi durumu ispat etmeye çalışalım. Bunun için her iki taraftaki <strong>config</strong> dosyalarında yer alan <strong>transactionFlow</strong> niteliklerine <strong>false </strong>değer verdiğimizi düşünelim. Örneği tekrardan çalıştıralım. İşte sonuç;</p>
<p><img src="/pics/2009%2f12%2fblg123_Runtime2.gif" alt="" /></p>
<p>Görüldüğü gibi operasyon çağrısı sonucu istemcide üretilen ve servis tarafında dosyaya yazılan <strong>DistributedIdentifier</strong> değerleri 0' dır. 0 olması zaten bir dağıtık transaction oluşturulmadığı/oluşturulamadığı anlamına gelmektedir. İşte bu kadar.<img title="Wink" src="/editors/tiny_mce3/plugins/emotions/img/smiley-wink.gif" alt="Wink" border="0" /> Tekrardan görüşünceye dek hepinize mutlu günler dilerim.</p>
<p><a href="https://buraksenyurt.com/pics/2009%2f12%2fTransactions.rar">Transactions.rar (54,45 kb)</a></p>2010-01-20T01:00:00+00:00wf 4.0bsenyurtGeçen gece ilginç bir rüya gördüm. Bir su birikintisine damlacıklar düşüyordu. Önceleri yavaş yavaş ve uzun aralıklarla düşen damlalar söz konusuydu. Zaman ilerledikçe her bir damlanın suya değdiği noktada bir isim bıraktığını görmeye başladım.https://buraksenyurt.com/pingback.axdhttps://buraksenyurt.com/post.aspx?id=50fa02a5-9b08-4ddb-a127-b00161525b9f0https://buraksenyurt.com/trackback.axd?id=50fa02a5-9b08-4ddb-a127-b00161525b9fhttps://buraksenyurt.com/post/Workflow-Foundation-40-Transaction-Flow-Beta-2#commenthttps://buraksenyurt.com/syndication.axd?post=50fa02a5-9b08-4ddb-a127-b00161525b9fhttps://buraksenyurt.com/post/Workflow-Foundation-40-Declarative-Validation-Beta-2Workflow Foundation 4.0 - Declarative Validation [Beta 2]2010-01-19T06:00:00+00:00bsenyurt<p><img style="float: right;" src="/pics/2009%2f12%2fblg111_Giris.gif" alt="" />Merhaba Arkadaşlar,</p>
<p>Sakin bir Cuma gününde bilgisayarın başında kahvemi yudumlarken ve M&M drajelerinden avuç avuç yerken araştırmalarıma devam ediyordum. Bir süredir <strong>Workflow Foundation 4.0</strong> ile birlikte gelen yenilikleri incelediğimden takip ettiğim bloglar ve MSDN üzerinde bu konu ile ilişkili yazıları okumaktaydım. Özelliklede son iki yazımda üzerinde durmaya çalıştığım özel aktivite bileşenlerinin doğrulanması konusunu irdelemekteydim. Bu yazımızda <strong>doğrulama(Validation)</strong> ile ilişkili araştırmalarımı sizlerle paylaşmaya devam ediyor olacağım.</p>
<p>Doğrulama işlemlerinin çeşitlerine baktığımızda<strong> Declarative Constraint</strong> isimli bir yaklaşımın daha olduğu görülmektedir. Bu yaklaşıma göre bir aktivite ile ilişkili doğrulama mantığının <strong>kısıt olaraktan(Constraint)</strong> ayrı bir tip ve metod içerisinde konuşlandırılması mümkündür. <em>(Hatta kod dışında XAML bazlı olaraktan kısıtların konulmasıda söz konusudur) </em><strong>Workflow Foundation</strong> alt yapısında bu tip dekleratif doğrulamalar için <strong>Constraint</strong> sınıfından yararlanılmaktadır. <strong>Constraint</strong> tipi aslında <strong>NativeActivity </strong>türevidir. Bir başka deyişle bir aktivitedir.</p>
<p><img src="/pics/2009%2f12%2fblg111_Constraint.gif" alt="" /></p>
<p>Yukarıdaki şekildende görülebileceği gibi <strong>Constraint</strong> <strong>abstract </strong>bir sınıftır<em>(dolayısıyla kendisinden türeyen tiplerin mutlaka uyması gereken kuralları bildiren, örneklenemeyen ama kendisinden türeyen tip örneklerini taşıyabilen bir sınıftır)</em> ve <strong>NaticeActivity</strong> tipinden türemektedir. Bu türetme nedeniyle aslında <strong>Workflow</strong> çalışma zamanının çeşitli materyallerine erişebildiğini(Scheduling, Bookmarks vb...) söyleyebiliriz. Peki pratikte kendi geliştireceğimiz aktivite bileşenleri için gerekli kısıtları nasıl koyabiliriz? <strong>MSDN</strong> üzerinde bu konu ile ilişkili olarak geliştirilen basit örnekte bir aktivite bileşeninin <strong>DisplayName</strong> özelliğinin 2 karakterden fazla olması gerekliliğinin örneklendiği görülmektedir. Bizde buna benzer bir kısıtlama geliştiriyor olacağız. Ancak örneğin farklı olması açısından, hayali yazılım şirketinin kod standartlarına göre DisplayName özelliğinin <strong>Chinook</strong> ön eki ile başlaması için bir kısıt getireceğiz. İşte Activity Library içerisinde tuttuğumuz örnek sınıf kodlarımız.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System.Activities;
using System.Activities.Validation;
namespace CustomActivities
{
public static class ActivityConstraints
{
// Constraint oluşturup geriye döndürecek basit bir static metod
public static Constraint ValidateActivityDisplayNameForCompanyCodeStandards()
{
DelegateInArgument<Activity> element = new DelegateInArgument<Activity>();
// Herhangibir Activity(T generic tipi olarak Activity kullanıldığından) bileşeninin doğrulanmasında kullanılacak olan Constraint tipi örneklenir.
// Constraint tipi aslında NativeActivity türevli bir Activity bileşenidir.
Constraint<Activity> constraint = new Constraint<Activity>
{
// Body kısmı doğrulama mantığını içermektedir ve ActivityAction tipindendir
Body = new ActivityAction<Activity, ValidationContext>
{
Argument1 = element,
Handler = new AssertValidation
{
// Warning bilgisi gösterilmeyecektir. Yani Error mesajı verilecektir. IsWarning özelliğinin varsayılan değeri false' dur.
IsWarning=false,
// e, ActivityContext tipinden bir referanstır. Dolayısıyla Constraint' in uygulanacağı aktivite bileşeninin güncel içeriğine erişilebilmesi mümkündür.
// Örnek doğrulamaya göre Actitiy örneğinin DisplayName özelliğinin Chinnok kelimesi ile başlaması beklenmektedir.
Assertion=new InArgument<bool>(
e=>
element.Get(e).DisplayName.StartsWith("Chinook")
),
// Eğer Chinook ismi ile başlanılmıyorsa bir hata mesajı verilir.
Message=new InArgument<string>("Şirketin kod standartları gereği, özel Activity adlarının Chinook ile başlaması gerekmektedir."),
DisplayName="DisplayNameValidationActivity"
}
}
};
return constraint;
}
}
}</pre>
<p><strong>ActivityConstraints</strong> isimli <strong>static</strong> sınıf içerisinde yer alan <strong>ValidateActivityDisplayNameForCompanyCodeStandards</strong> isimli metod geriye <strong>Constraint</strong> tipinden bir referans döndürmektedir. <strong>Constraint</strong> tipinin üretimi sırasında dikkat edileceği üzere <strong>Handler</strong> özelliğine <strong>AssertValidation</strong> tipinden bir referans atanmaktadır. İşte bu sınıfın örneklenmesi sırasında kullanılan <strong>Assertion</strong> özelliği ilede bir <strong>Expression</strong> tanımlaması yapılmakta ve bu kısıtın uygulandığı <strong>Activity</strong> bileşeninin <strong>DisplayName</strong> özelliğinin <strong>Chinook</strong> ile başlayıp başlamadığı kontrol edilmektedir. Bu ifadeden dönecek değer göre <strong>Message </strong>özelliğine atanan bilginin derleme zamanında gösterilmesi sağlanmaktadir. <strong>IsWarning</strong> özelliği varsayılan olarak <strong>false</strong> değere sahiptir ve buna göre mesajın bir <strong>Error</strong> olarak gösterilmesi sağlanmaktadır. Ancak bu özelliğe <strong>true</strong> değerini atayaraktan <strong>Warning</strong> olarak gösterilmesi de sağlanabilir. Peki bu kısıt bir aktivite bileşenine nasıl uygulanabilir? Aslında bunun için geliştiriken aktiviteye bir bildirimde bulunulması yeterlidir. Aşağıdaki kod parçasında yer alan aktivite bileşeninde bu durum ele alınmaktadır.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System.Activities;
using System.Activities.Validation;
namespace CustomActivities
{
public enum LogSource
{
File,
Database,
WebService,
System
}
// Loglama yapan örnek bir aktivitedir.
public sealed class LogActivity
: CodeActivity<bool>
{
public InArgument<LogSource> LogSourceType { get; set; }
public LogActivity()
{
// Constraint' lerin bir aktivite ile ilişkilendirilebilmesi için base referans üzerinden ilgili koleksiyona eklenmesi gerekmektedir.
// Constraints özelliği bir koleksiyonu referans ettiği için bir aktiviteye birden fazla Constraint yüklenmesi mümkündür.
base.Constraints.Add(ActivityConstraints.ValidateActivityDisplayNameForCompanyCodeStandards());
}
protected override bool Execute(CodeActivityContext context)
{
//TODO@Burak: Gerçektende loglama işlemi yapılması için gerekli kodlar yazılmalı
switch (LogSourceType.Get(context))
{
case LogSource.File:
break;
case LogSource.Database:
break;
case LogSource.WebService:
break;
case LogSource.System:
break;
default:
break;
}
return true;
}
}
}</pre>
<p>Burada odaklanılması gereken tek bir yer vardır...<strong>Yapıcı metodun(Constructor)</strong> içerisinde yer alan kod satırı. Dikkat edileceği üzere <strong>Constraints</strong> özelliği üzerinden <strong>ValidateActivityDisplayNameForCompanyCodeStandards</strong> metodunun dönüş referansının ilgili koleksiyona eklenmesi sağlanmaktadır. Buna göre, <strong>LogActivity</strong> bileşeninin <strong>Visual Studio</strong> ortamında kullanıldığı durumlarda <strong>DisplayName</strong> özelliğinin ilgili kısıta göre kontrol edileceği bildirilmiş olmaktadır. Dilerseniz birde bileşeni test edelim. İşte bileşeni örnek bir Workflow üzerine ilk kez sürükleyip bıraktığımızdaki durum;</p>
<p><img src="/pics/2009%2f12%2fblg111_Error.gif" alt="" /></p>
<p>Görüldüğü üzere <strong>DisplayName</strong> özelliği için bir hata mesajı alınmıştır. Buna göre Chinook ön ekin kullandığımızda sorunun ortadan kalktığı görülebilir.</p>
<p><img src="/pics/2009%2f12%2fblg111_NoError.gif" alt="" /></p>
<p><strong>Constraint</strong> kullanımı dikkat edileceği üzere herhangibir aktivite bileşeni için kısıt koyabilmeyi olanaklı hale getirmektedir. <strong>Constraint</strong> kullanımında farklı durumlarda söz konusudur. Örneğin bir aktivitenin içerisinde yer alan tüm alt aktiviteler için geçerli olacak kısıtların konulmasıda mümkün olabilir. Bu son derece doğaldır nitekim <strong>Constraint</strong> sınıfı örneklenirken, ilişkilendirildiği aktivite içeriğine erişebilmektedir. Burada <strong>DelegateInArgument<Activity></strong> temsilci tipinin büyük rolü vardır. Öyleki Expression tanımlamasının yapıldığı ve doğrulama mantığının gerçekleştirildiği yerde, güncel aktivite referansına ulaşmak için<strong> element.Get(e)</strong> söz dizimi kullanılmaktadır. Tabiki bu yazımızda<strong> Declarative Constraint</strong> kullanımını çok basit seviyede ele almaya çalıştık. En güncel ve detaylı bilgiyi elbetteki <a title="Declarative Constraints" href="http://msdn.microsoft.com/en-us/library/ee358736(VS.100).aspx">MSDN </a>üzerinde bulabilirsiniz. Böylece geldik bir yazımızın daha sonuna. Tekrardan görüşünceye dek hepinize mutlu günler dilerim.</p>
<p><a href="https://buraksenyurt.com/pics/2009%2f12%2fDeclerativeConstraints.rar">DeclerativeConstraints.rar (50,29 kb)</a></p>2010-01-19T06:00:00+00:00wf 4.0bsenyurtSakin bir Cuma gününde bilgisayarın başında kahvemi yudumlarken ve M&M drajelerinden avuç avuç yerken araştırmalarıma devam ediyordum. Bir süredir Workflow Foundation 4.0 ile birlikte gelen yenilikleri incelediğimden takip ettiğim bloglar ve MSDN üzerinde bu konu ile ilişkili yazıları okumaktaydım. Özelliklede son iki yazımda üzerinde durmaya çalıştığım özel aktivite bileşenlerinin doğrulanması konusunu irdelemekteydim. Bu yazımızda doğrulama(Validation) ile ilişkili araştırmalarımı sizlerle paylaşmaya devam ediyor olacağım.https://buraksenyurt.com/pingback.axdhttps://buraksenyurt.com/post.aspx?id=5b0c6364-8449-48ce-80e5-863b7c5f24890https://buraksenyurt.com/trackback.axd?id=5b0c6364-8449-48ce-80e5-863b7c5f2489https://buraksenyurt.com/post/Workflow-Foundation-40-Declarative-Validation-Beta-2#commenthttps://buraksenyurt.com/syndication.axd?post=5b0c6364-8449-48ce-80e5-863b7c5f2489https://buraksenyurt.com/post/Workflow-Foundation-40-Dogrulama(Validation)Workflow Foundation 4.0 - Kodlama Zamanında Doğrulama(Validation)2010-01-15T01:08:00+00:00bsenyurt<p><img style="float: right;" src="/pics/2009%2f12%2fblg110_Giris.jpg" alt="" />Merhaba Arkadaşlar,</p>
<p>Bazen nerede duracağımızı bilmemiz gerekir ve bazende, mümkün olduğunca erken durup bazı şeyleri değiştirerek ilerlememiz...Bu teori yazılım geliştirmeninde pek çok noktasında karşımıza çıkmaktadır. Durmamız gereken noktalardan birisi, uygulamaların ürettiği ve önceden fark edebileceğimiz hatalardır<em>(Genellikle Exception' ları düşünebiliriz)</em>. Ancak bazı olası hataların uygulamaların çalışması sırasında değil, çalıştırılmaya başlamadan önce bilinmesinde hem zaman hemde maliyet kazancı açısından yarar vardır. Şimdi elimizdeki materyalleri bir düşünelim.</p>
<p>Ürün geliştirmek için kullandığımız <strong>Visual Studio</strong> gibi gelişmiş bir araç, <strong>.Net Framework </strong>platformu vb...O halde bazı hataların çalışma zamanı yerine daha geliştirme aşamasındayken IDE üzerinde fark edilmesinin önemli olduğunu söyleyebiliriz. Peki geliştirme safhasında, örneğin bir Workflow aktivitesini kullanırken...Hımmmm...Sanırım nereye varmak istediğimi anladınız.<img title="Wink" src="/editors/tiny_mce3/plugins/emotions/img/smiley-wink.gif" alt="Wink" border="0" /> Bu yazımızda, özel aktivite bileşenlerinin kodlama zamanındayken olası hataları nasıl bildirebileceğini ve böylece <strong>doğrulamanın(Validation)</strong> nasıl sağlanabileceğini incelemeye çalışacağız.</p>
<p>Bundan önceki yazılarımızda özel aktivite bileşenlerimizi nasıl geliştirebileceğimizi incelemeye çalışmıştık. Bu amaçla yazdığımız örneklermizde <strong>CodeActivity</strong> ve <strong>AsyncCodeActivity</strong> türevli bileşenler geliştirmiştik. Özel aktivite bileşenleri geliştirilmesi sırasında dikkat edilmesi gereken önemli konulardan biriside kodlama zamanında gerçekleştirilmesini istediğimiz <strong>doğrulama(Validation)</strong> işlemleridir. Doğrulama için <strong>Workflow Foundation 4.0 </strong>tarafında kullanılabilen birden fazla teknik bulunmaktadır. <strong>Nitelik(Attribute)</strong> bazlı kullanım dışında <strong>Imperative</strong> ve <strong>Declerative</strong> olaraktan da doğrulama işlemlerini gerçekleştirebiliriz. Aslında konuyu anlamanın en güzel yolu öncelikli olarak sorunu ortaya koymaktan geçmektedir. Bu sebepten aşağıdaki gibi bir <strong>CodeActivity</strong> bileşeni tasarladığımızı düşünelim.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System.Activities;
using System.IO;
using System;
using System.Activities.Expressions;
namespace CustomActivities
{
public sealed class FileCopy
: CodeActivity
{
public InArgument<string> Source { get; set; }
public InArgument<string> Destination { get; set; }
protected override void Execute(CodeActivityContext context)
{
File.Copy(Source.Get(context), Destination.Get(context));
}
}
}</pre>
<p><strong>FileCopy</strong> isimli aktivite bileşenimizin görevi <strong>Source</strong> özelliğinde belirtilen dosyayı, <strong>Destination</strong> özelliğinde belirtilen yere kopyalamaktır. Bu işlem için <strong>CodeActivity</strong> tarafından gelip <strong>ezilen(override)</strong> <strong>Execute</strong> metodu içerisinde, <strong>File </strong>sınıfının <strong>static Copy </strong>metodundan yararlanılmaktadır. Ne varki bu aktivite bileşeninin özellikle çalışma zamanında üreteceği bazı sorunlar vardır. Aslında bunları şimdiden tahmin etmemiz son derece kolaydır.</p>
<p>Herşeyden önce, <strong>InArgument<string></strong> tipinden olan <strong>Source</strong> ve <strong>Destination</strong> özelliklerinin boş geçilmemesi yani veri ile doldurulması şarttır. Nitekim <strong>null</strong> verilerin <strong>Copy</strong> metodu içerisinde kullanılması söz konusu olamaz. Diğer yandan <strong>Source</strong> özelliğinde belirtilen dosyanın, sistemde gerçekten var olması gerekmektedir. Dolayısıyla <strong>Source</strong> özelliğinde bir değer olsa bile bunun geçerli bir dosya olup olmadığına bakılmalıdır. Üçüncü olaraktan <strong>Destination</strong> özelliğinde belirtilen dosya adının geçerli olması ve belkide <strong>Source</strong> ile belirtilen dosya uzantısında olması gerekmektedir. Hatta hedef dosya zaten var ise üzerine yazılması durumu söz konusudur. Bu vakaların herhangibirinin çalışma zamanında gerçeklenmesi sonrası <strong>istisnalar(Exceptions)</strong> ile karşılaşılması kaçınılmazdır. Söz gelimi aktivitemizi bu haliyle örnek bir <strong>Workflow</strong> içerisinde icra ettirdiğimizde çalışma zamanında aşağıdaki istisna mesajını alırız.</p>
<p><img src="/pics/2009%2f12%2fblg110_Exception.gif" alt="" /></p>
<p><strong>Source </strong>özelliğinde null değer olduğundan <strong>Copy </strong>operasyonunun icrası sırasında <strong>ArgumentNullException </strong>alınmıştır. Oysaki bu hatanın çalışma zamanında değil kodlama zamanında, yani <strong>Visual Studio</strong> ortamında daha tasarımı gerçekleştirirken farketmemiz çok önemlidir. Bu bize zaman ve maliyet kazancı olarak geri dönecektir. İşte doğrulamanın sağlanması gereken yerlerden birisi burasıdır. Peki bunu nasıl gerçekleştirebiliriz? Öncelikli olarak <strong>Source</strong> ve <strong>Destination</strong> isimli <strong>InArgument<string></strong> tipinden olan özelliklerin boş bırakılmamasını sağlamalıyız. Bunun için ilgili özellikleri <strong>RequiredArgument</strong> niteliği ile aşağıdaki kod parçasında görüldüğü gibi işaretlememiz yeterli olacaktır.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">[RequiredArgument]
public InArgument<string> Source { get; set; }
[RequiredArgument]
public InArgument<string> Destination { get; set; }</pre>
<p>Bu durumda tasarım zamanında aşağıdaki görüntü ile karşılaşırız.</p>
<p><img src="/pics/2009%2f12%2fblg110_DesignTime.gif" alt="" /></p>
<p>Dikkat edileceği üzere <strong>Source</strong> ve <strong>Destination</strong> değelerinin doldurulması zorunlu hale getirilmiştir. Üstelik bu durum derleme işleminden sonra açık bir şekilde adeta geliştiricinin gözüne sokulmaktadır. <img title="Laughing" src="/editors/tiny_mce3/plugins/emotions/img/smiley-laughing.gif" alt="Laughing" border="0" /> <strong>RequiredArgument </strong>niteliği ile ilişkili olarak dikkat edilmesi gereken noktalardan biriside <strong>Argument</strong> tiplerine uygulandığında işe yarıyor olmasıdır. Yani <strong>Soruce</strong> ve <strong>Destination</strong> özelliklerinin <strong>string</strong> tipinden olmaları gibi bir durumda bu niteliğin bir etkisi olmayacaktır.</p>
<p>İlk vakayı çözümledik. Artık dosya adlarını girdiğimizi düşünebiliriz. Sıradaki sorun <strong>Source</strong> özelliğine girilen dosyanın sistemde olmaması halinde ortaya çıkacaktır. Buna göre yine kopyalama işlemi sırasında bir çalışma zamanı hatası alınacaktır. Durumu irdeleyebilmek için <strong>Source</strong> ve <strong>Destination</strong> özelliklerini aşağıdaki şekilde görüldüğü gibi ayarladığımızı düşünelim.</p>
<p><img src="/pics/2009%2f12%2fblg110_SourceOk.gif" alt="" /></p>
<p>Bu durumda çalışma zamanında aşağıdaki hata mesajını alırız.</p>
<p><img src="/pics/2009%2f12%2fblg110_Exception2.gif" alt="" /></p>
<p>Tabi burada c:\ klasörü içerisinde <strong>Source.txt</strong> isimli bir dosyanın gerçektende var olmadığını düşünüyoruz. Buradaki istisnaya göre kaynak dosyanın önceden kontrol edilmesi ve derleme işleminden sonra geliştiriciye bir uyarı veya hata mesajı ile durumun bildirilmesi istenebilir. Ancak burada basit bir nitelik yardımıyla aşabileceğimizin ötesinde bir durum vardır. Nitekim doğrulama için özel bir <strong>iş mantığı(Bussines Logic)</strong> bulunmaktadır. İşte bu tip doğrulamaları gerçekleştirebilmek için <strong>CodeActivity</strong> ve <strong>NativeActivity</strong> türevlerinde <strong>CacheMetadata</strong> isimli metodun ezilmesi ve <strong>Visual Studio</strong> ortamına doğrulama ile ilişkili bilgilendirmenin yapılması gerekmektedir. Sözün özü <strong>FileCopy</strong> aktivite bileşenimizi aşağıdaki hale getirmemiz yeterli olacaktır <img title="Wink" src="/editors/tiny_mce3/plugins/emotions/img/smiley-wink.gif" alt="Wink" border="0" /></p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System.Activities;
using System.IO;
using System;
using System.Activities.Expressions;
namespace CustomActivities
{
public sealed class FileCopy
: CodeActivity
{
[RequiredArgument]
public InArgument<string> Source { get; set; }
[RequiredArgument]
public InArgument<string> Destination { get; set; }
protected override void Execute(CodeActivityContext context)
{
File.Copy(Source.Get(context), Destination.Get(context));
}
protected override void CacheMetadata(CodeActivityMetadata metadata)
{
base.CacheMetadata(metadata);
string source = ((Literal<string>)Source.Expression).Value;
if (!File.Exists(source))
metadata.AddValidationError(new System.Activities.Validation.ValidationError("Kaynak dosya bulunamadı.", true));
}
}
}</pre>
<p>Burada <strong>Source</strong> özelliğinin değerine bakılmakta ve belirtilen dosyanın sistemde gerçekten var olup olmadığı tespit edilmektedir. Eğer söz konusu dosya sistemde yok ise <strong>"Kaynak dosya bulunamadı."</strong> içeriğine sahip bir <strong>uyarı mesajı(Warning)</strong> üretilir. Uyarı mesajı diyoruz çünkü sonda yer alan <strong>true</strong> değeri bunu sağlamaktadır. Yine derleme işleminden sonra oluşacak durum aşağıdaki gibidir.</p>
<p><img src="/pics/2009%2f12%2fblg110_Warning.gif" alt="" /></p>
<p>Tabi eğer <strong>true</strong> yerine <strong>false</strong> değerini kullanırsak aşağıda görülen nur topu gibi<strong> error'</strong> un sahibi oluruz. <img title="Smile" src="/editors/tiny_mce3/plugins/emotions/img/smiley-smile.gif" alt="Smile" border="0" /></p>
<p><img src="/pics/2009%2f12%2fblg110_WarningFalse.gif" alt="" /></p>
<p>Bu adımdan sonra geçerli bir kaynak dosyayı <strong>Source</strong> özelliğine atayarak devam edersek <strong>Destination</strong> özelliğine atanan değer ile ilişkili kontrolleri yapmamız gerektiği sonucuna varabiliriz. Buna göre hedef dosyanın kaynak dosya ile uzantı bakımından uyumlu olması sağlanabilir. Tabiki arka arkaya yapılan çalıştırmalar sonrasında hedef dosya zaten var ise <strong>overwrite</strong> ile ilişkili hataların oluşması da söz konusudur. Bu iki doğrulama işlemini siz değerli okurlarıma bir antrenman olması için bırakıyorum <img title="Wink" src="/editors/tiny_mce3/plugins/emotions/img/smiley-wink.gif" alt="Wink" border="0" /> Böylece geldik bir yazımızın daha sonuna. Tekrardan görüşünceye dek hepinize mutlu günler dilerim.</p>
<p><a href="https://buraksenyurt.com/pics/2009%2f12%2fCustomActivityValidation.rar">CustomActivityValidation.rar (50,30 kb)</a></p>2010-01-15T01:08:00+00:00wf 4.0wfworkflow foundationbsenyurtBazen nerede duracağımızı bilmemiz gerekir ve bazende, mümkün olduğunca erken durup bazı şeyleri değiştirerek ilerlememiz...Bu teori yazılım geliştirmeninde pek çok noktasında karşımıza çıkmaktadır. Durmamız gereken noktalardan birisi, uygulamaların ürettiği ve önceden fark edebileceğimiz hatalardır(Genellikle Exception' ları düşünebiliriz).https://buraksenyurt.com/pingback.axdhttps://buraksenyurt.com/post.aspx?id=60abfd62-9b45-4608-95ae-d7e1b645bde90https://buraksenyurt.com/trackback.axd?id=60abfd62-9b45-4608-95ae-d7e1b645bde9https://buraksenyurt.com/post/Workflow-Foundation-40-Dogrulama(Validation)#commenthttps://buraksenyurt.com/syndication.axd?post=60abfd62-9b45-4608-95ae-d7e1b645bde9