<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.microsoft.co.il/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Eran Sakal -  Blog</title><link>http://blogs.microsoft.co.il/blogs/esakal/</link><description>Hebrew tech blog focusing on C#, asp.net web development, design patterns, javascript and more.</description><dc:language>en</dc:language><generator>CommunityServer 2007.1 (Build: 20917.1142)</generator><item><title>VS2010 debugging problems - "The breakpoint will not currently be hit..."</title><link>http://blogs.microsoft.co.il/blogs/esakal/archive/2011/11/11/vs2010-debugging-problems-quot-the-breakpoint-will-not-currently-be-hit-quot.aspx</link><pubDate>Fri, 11 Nov 2011 22:30:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:929650</guid><dc:creator>Eran Sakal</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.microsoft.co.il/blogs/esakal/archive/2011/11/11/vs2010-debugging-problems-quot-the-breakpoint-will-not-currently-be-hit-quot.aspx#comments</comments><description>&lt;p&gt;&lt;strong&gt;This article applies to the following technologies: &lt;/strong&gt;Silverlight, C#, Visual Studio 2010 (vs2010)&lt;/p&gt;
&lt;p&gt;There are times when Visual Studio decides that you have too much spare time and starts acting weird by ignoring your breakpoints while debugging.&amp;nbsp; This behavior has multiple symptoms:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Your breakpoints are shown as empty red circles instead of the regular full circles&lt;/li&gt;
&lt;li&gt;When hovering with the mouse on the breakpoint you receive the annoying message: &amp;quot;The breakpoint will not currently be hit...&amp;quot;&lt;/li&gt;
&lt;li&gt;And most importantly, Visual Studio ignores your breakpoints&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/image_30C51BBC.png"&gt;&lt;img style="BACKGROUND-IMAGE:none;BORDER-BOTTOM:0px;BORDER-LEFT:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;PADDING-TOP:0px;" title="image" border="0" alt="image" src="http://blogs.microsoft.co.il/blogs/esakal/image_thumb_2EA81CF3.png" width="454" height="133" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The following steps should hopefully solve your problem. You can try them in any order that you prefer.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;step 1&lt;/strong&gt; - Delete temporary asp.net files from your machine.&lt;/p&gt;
&lt;p&gt;You can find the temporary directory at &amp;quot;C:\windows\Microsoft.NET\Framework\&lt;strong&gt;v4.0.30319&lt;/strong&gt;\Temporary ASP.NET Files&amp;quot;. Notice that the framework version (bolded text) represents the framework which is used by your server and can vary between machines. To determine the version which is currently in use, click on the &lt;em&gt;Development Server &lt;/em&gt;icon on the system tray and take note of the ASP.NET Version field, as seen in the following screenshot:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/image_451ABB7A.png"&gt;&lt;img style="BACKGROUND-IMAGE:none;BORDER-BOTTOM:0px;BORDER-LEFT:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;PADDING-TOP:0px;" title="image" border="0" alt="image" src="http://blogs.microsoft.co.il/blogs/esakal/image_thumb_7BA866BE.png" width="404" height="236" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;step 2 – &lt;/strong&gt;Clear your browser cache, then re-open the browser.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;step 3&lt;/strong&gt; – (most elusive) - Verify that you are &lt;strong&gt;&lt;em&gt;not &lt;/em&gt;&lt;/strong&gt;running vs2010 in compatibility mode.&lt;/p&gt;
&lt;p&gt;Right click on the Visual Studio icon –&amp;gt; properties –&amp;gt; compatibility –&amp;gt; un-check&amp;nbsp;the option &amp;#39;Run this program in compatibility mode for&amp;#39;, as seen in the following screenshot:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/image_66D66E3E.png"&gt;&lt;img style="BACKGROUND-IMAGE:none;BORDER-BOTTOM:0px;BORDER-LEFT:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;PADDING-TOP:0px;" title="image" border="0" alt="image" src="http://blogs.microsoft.co.il/blogs/esakal/image_thumb_37384FB2.png" width="404" height="98" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;step 4 &lt;/strong&gt;– Remove&amp;nbsp;the &amp;#39;bin&amp;#39; and &amp;#39;obj&amp;#39; directories from all your projects in the solution.&lt;/p&gt;
&lt;p&gt;These folders are created by each project while compiling. They are not shown in the Visual&amp;nbsp;Studio environment so in order to delete them&amp;nbsp;you should use your system&amp;#39;s search dialog.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;step 5 &lt;/strong&gt;- Delete the &amp;#39;suo&amp;#39; file of the solution.&lt;/p&gt;
&lt;p&gt;This is a hidden file located in the same place and named the same as your solution file.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;step 6 – &lt;/strong&gt;Make sure you are executing vs2010 on &amp;#39;Debug&amp;#39; configuration mode and not &amp;#39;Release&amp;#39; mode. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;step 7 – &lt;/strong&gt;Reset vs2010 using the &amp;quot;Import and Export Settings Wizard&amp;quot;&lt;/p&gt;
&lt;p&gt;These settings affect the way Visual Studio behaves according to your programming language (C++, C#, F#). They also affect the debugger feature. To reset vs2010 settings you may read the &lt;a href="http://brian.chipsofttech.com/blogs/brian/post/VS-2010-e28093-reset-your-options.aspx" target="_blank"&gt;following article&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;step 8 – &lt;/strong&gt;Make sure that the web project is set to be the startup project. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;step 9 &lt;/strong&gt;– Access the web project properties –&amp;gt; Web –&amp;gt; Verify that both &amp;#39;ASP.NET&amp;#39; and &amp;#39;Silverlight&amp;#39; are marked.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/image_0323B05F.png"&gt;&lt;img style="BACKGROUND-IMAGE:none;BORDER-BOTTOM:0px;BORDER-LEFT:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;PADDING-TOP:0px;" title="image" border="0" alt="image" src="http://blogs.microsoft.co.il/blogs/esakal/image_thumb_27D4C7D6.png" width="504" height="200" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If all of this doesn&amp;#39;t work you may try the &lt;a href="http://it.toolbox.com/blogs/programming-life/debugging-net-applications-stopping-the-breakpoint-will-not-currently-be-hit-message-26262" target="_blank"&gt;following article&lt;/a&gt; which contains additional suggestions for solving this issue.&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=929650" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/Tips/default.aspx">Tips</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/Silverlight4/default.aspx">Silverlight4</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/VS2010/default.aspx">VS2010</category></item><item><title>Re-using WCF service among several Silverlight applications</title><link>http://blogs.microsoft.co.il/blogs/esakal/archive/2011/10/05/creating-silverlight-wcf-ria-service-in-class-library-assembly.aspx</link><pubDate>Wed, 05 Oct 2011 22:15:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:908248</guid><dc:creator>Eran Sakal</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.microsoft.co.il/blogs/esakal/archive/2011/10/05/creating-silverlight-wcf-ria-service-in-class-library-assembly.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/image_102ACB58.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://blogs.microsoft.co.il/blogs/esakal/image_thumb_6D868CDC.png" width="404" height="177" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;This article is about creating WCF RIA service in class library assembly instead of in the Silverlight application. For&lt;em&gt; &lt;/em&gt;unknown reason (at least for me) most, if not all of the Silverlight samples implement the service logic in the main Silverlight application project. But since MVVM is all about de-coupling and re-using, Those services should be implemented in class library and exposed by the application.&lt;/p&gt;  &lt;h2&gt;&lt;/h2&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/posts/201109/WCFLargeBuffer.zip" target="_blank"&gt;Press here to download demo solution&lt;/a&gt;. In this solution you will find a working service as shown above.&lt;/p&gt;  &lt;h1&gt;Creating the service in class library project&lt;/h1&gt;  &lt;p&gt;&lt;strong&gt;1&lt;/strong&gt; Open your application solution.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2&amp;#160; &lt;/strong&gt;Add project of type &amp;#39;Class Library&amp;#39; (Notice not to select &amp;#39;Silverlight class library&amp;#39;).&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;3 &lt;/strong&gt;In the newly created project add an item of type &amp;#39;WCF service&amp;#39;. This file extension is &amp;#39;.cs&amp;#39; and not &amp;#39;.svc&amp;#39;. Don&amp;#39;t worry about it at the moment.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/image_1F173E5C.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://blogs.microsoft.co.il/blogs/esakal/image_thumb_18C04201.png" width="404" height="231" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Visual studio creates a regular WCF service with service contract (interface), service concrete class and relevant attributes. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;4&amp;#160; &lt;/strong&gt;Add one or more methods to the service.&lt;/p&gt;  &lt;h1&gt;Exposing the service from the Silverlight application&lt;/h1&gt;  &lt;p&gt;The following steps should be executed in the &lt;em&gt;Silverlight web project.&lt;/em&gt; We are going to create a service which will operate as proxy to the service we created in previous steps. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;5 &lt;/strong&gt;Add a project reference to the WCF service project from the Silverlight web project.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;6 &lt;/strong&gt;Add an item of type &amp;#39;Silverlight-enabled WCF service&amp;#39;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/image_5B033477.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://blogs.microsoft.co.il/blogs/esakal/image_thumb_4D20C8AF.png" width="404" height="231" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;7 &lt;/strong&gt;Check if a service endpoint was added to &amp;#39;system.serviceModel&amp;#39; element&amp;#160; in the &amp;#39;web.config&amp;#39; file. If so, delete the configuration for that service.&lt;/p&gt;  &lt;p&gt;Visual studio created regular empty service. Our goal is to use this service as proxy to the service that you created earlier. In the following steps you will convert the service to a proxy using inheritance.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;8 &lt;/strong&gt;Open the file with the extension &amp;#39;svc.cs&amp;#39; of the newly created service.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;9 &lt;/strong&gt;Remove the class&amp;#39; content as well as the attribute &amp;#39;ServiceContract&amp;#39;.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;10 &lt;/strong&gt;Inherit from the service class you created in the separate project.&lt;/p&gt;  &lt;p&gt;If you have reached this step then you finished creating a service in a class library. You may now create a service reference to the service proxy and use it as all the regular services. &lt;/p&gt;  &lt;p&gt;Note, If you followed the instructions carefully you probably noticed that you didn&amp;#39;t need to add any configuration to the configuration file &amp;#39;web.config&amp;#39;. The reason is that Silverlight runtime engine creates dynamic configuration on the fly when a client tries to use the service. &lt;/p&gt;  &lt;h1&gt;Recap&lt;/h1&gt;  &lt;p&gt;In this article I demonstrated how you can easily create services in class library assembly. Doing so allow you to re-use the service between applications.&lt;/p&gt;  &lt;h2&gt;Demo&lt;/h2&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/posts/201109/WCFLargeBuffer.zip" target="_blank"&gt;Press here to download demo solution&lt;/a&gt;. In this solution you will find a working service as shown above.&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=908248" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/Tips/default.aspx">Tips</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/Silverlight4/default.aspx">Silverlight4</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/WCF/default.aspx">WCF</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/RIA/default.aspx">RIA</category></item><item><title>Silverlight - How to support uploading files larger than 16K in WCF RIA services</title><link>http://blogs.microsoft.co.il/blogs/esakal/archive/2011/10/03/silverlight-how-to-support-uploading-files-larger-then-16k-in-wcf-ria-services.aspx</link><pubDate>Mon, 03 Oct 2011 16:35:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:905259</guid><dc:creator>Eran Sakal</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.microsoft.co.il/blogs/esakal/archive/2011/10/03/silverlight-how-to-support-uploading-files-larger-then-16k-in-wcf-ria-services.aspx#comments</comments><description>&lt;p&gt;&lt;strong&gt;This article applies to the following technologies:&lt;/strong&gt; Silverlight, WCF RIA, Azure&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/exception1_7E3B993F.jpg"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="exception1" border="0" alt="exception1" src="http://blogs.microsoft.co.il/blogs/esakal/exception1_thumb_03E68D19.jpg" width="504" height="200" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/exception2_75C79E1B.jpg"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="exception2" border="0" alt="exception2" src="http://blogs.microsoft.co.il/blogs/esakal/exception2_thumb_7D8F90BD.jpg" width="504" height="166" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://microsoftblog.eransakal.com/wcfLargeBuffer/" target="_blank"&gt;press here to view live example&lt;/a&gt;&lt;/p&gt;  &lt;h1&gt;Intro&lt;/h1&gt;  &lt;p&gt;I have written this article after spending some time configuring WCF RIA service in my application. I wanted to create a service which will allow uploading files larger than 16KB. The problem was that Silverlight doesn&amp;#39;t handle exceptions in WCF very well, which makes it hard to troubleshoot. In this article I will cover three major exceptions that I had encountered during the implementation.&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;In this article I plan to cover the following topics.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Section 1 - Revealing the actual exception behind &lt;strong&gt;&amp;#39;HTTP/1.1 500 Internal Server Error&amp;#39;&lt;/strong&gt; / &lt;strong&gt;&amp;#39;&lt;em&gt;The remote server returned an error: NotFound&amp;#39;&lt;/em&gt;&lt;/strong&gt;. &lt;/li&gt;    &lt;li&gt;Section 2 - Solving the annoying exception &lt;strong&gt;&amp;#39;&lt;em&gt;The maximum array length quota (16384) has been exceeded while reading XML data...&amp;#39;&lt;/em&gt;&lt;/strong&gt;. &lt;/li&gt;    &lt;li&gt;Section 3 - Overcoming the exception &amp;#39;&lt;em&gt;&lt;strong&gt;HTTP/1.1 415 Unsupported Media Type&lt;/strong&gt;&amp;#39;&lt;/em&gt; while calling a WCF Silverlight service. &lt;/li&gt; &lt;/ul&gt;  &lt;h2&gt;Download Sample&lt;/h2&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/posts/201109/WCFLargeBuffer.zip" target="_blank"&gt;Press here to download demo solution&lt;/a&gt;. In this solution you will find a working service as shown above.&lt;/p&gt;  &lt;h1&gt;Section 1 - Revealing the actual exception behind &amp;#39;&lt;em&gt;The remote server returned an error: NotFound&amp;#39;&lt;/em&gt;&lt;/h1&gt;  &lt;p&gt;Silverlight fails to report on WCF exceptions correctly. Most of the exceptions being thrown, end up as a with general exception which conceal the actual problem.&amp;#160; Some exceptions can be seen using Fiddler on the client side. A better and more profound way should be logging the details of the actual exception on the server side. &lt;/p&gt;  &lt;p&gt;In this section I will show you how to enable WCF logging on the server. I will use some tools that can be found in VS2010.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;s1.1 &lt;/strong&gt;Open the requested project in VS2010.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;s1.2&lt;/strong&gt; In the upper menu select &amp;#39;&lt;em&gt;Tools –&amp;gt; WCF service configuration tools&amp;#39;&lt;/em&gt;. The tool will be opened.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;s1.3&lt;/strong&gt; Open the file &amp;#39;web.config&amp;#39; located in the web project (&amp;#39;&lt;em&gt;File –&amp;gt; Open –&amp;gt; Config file&amp;#39;&lt;/em&gt;).&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;s1.4&lt;/strong&gt; In the left panel named &amp;#39;Configuration&amp;#39; expand the node &amp;#39;Diagnosis&amp;#39;.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;s1.5&lt;/strong&gt; Enable WCF &amp;#39;Tracing&amp;#39; as shown in the following image.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/image_6735CDD0.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://blogs.microsoft.co.il/blogs/esakal/image_thumb_53984862.png" width="404" height="316" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;s1.6 &lt;/strong&gt;Remember the path of the log file that will be used to store the log entries. In the example above the file path is &amp;#39;c:\web_tracelog.svclog&amp;#39;. You can leave the default path as is.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;s1.7 &lt;/strong&gt;Save your changes in the tool and return to vs2010. The &amp;#39;web.config&amp;#39; file should be updated.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;s1.8 &lt;/strong&gt;Run your application and reproduce the exception.&lt;/p&gt;  &lt;p&gt;In order to read the log file you will use another tool which has already been installed on your machine as part of the VS2010 installation and is called &amp;#39;&lt;a href="http://msdn.microsoft.com/en-us/library/ms732023.aspx" target="_blank"&gt;Service Trace Viewer Tool&lt;/a&gt;&amp;#39;. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;s1.9 &lt;/strong&gt;Use the Windows explorer to open the log file. The tool is mapped as default for files with extension ‘.svclog’ thus the tool should be opened automatically.&lt;/p&gt;  &lt;p&gt;This tool is used to read the log easily. In the ‘Activity’ table each row represents a WCF activity in the server. Rows marked in red indicate that the activity reported an exception. Select the last row marked in red. In the right panel select the message which is also marked in red…&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/image_26DF68BC.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://blogs.microsoft.co.il/blogs/esakal/image_thumb_563DB1BB.png" width="404" height="359" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The actual exception should be shown in the tool. Don’t forget to remove the log from the ‘web.config’ file before going to production (Removing can be done by the tool by setting &amp;#39;Tracing&amp;#39; to off).&lt;/p&gt;  &lt;h1&gt;Section 2 - Solving the annoying exception “&lt;em&gt;The maximum array length quota (16384) has been exceeded while reading XML data&lt;/em&gt;”&lt;/h1&gt;  &lt;p&gt;This exception is raised when trying to send messages in a wcf service larger which are larger than 16KB. In regular WCF usage you are registering the services in the &amp;#39;web.config&amp;#39;. When using Silverlight WCF RIA you don&amp;#39;t register the services because the Silverlight framework performs it for you during run-time using the default configuration. If you want to customize one of the services&amp;#160; (i.e a service which retrieves a file or some other huge chunk of data) you should perform the following steps:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;s2.1&lt;/strong&gt; Open file &amp;#39;ServiceReferences.ClientConfig&amp;#39; in the &lt;em&gt;Silverlight application project&lt;/em&gt;. This file contains all the services which are used in the Silverlight application.&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;s2.2&lt;/strong&gt; Create a custom binding as shown in the attached code sample. Modify the sample according to your service information such as service address, contract and binding/endpoint names. The important part in this step is that in lines 3-8 you create a custom binding with the attributes &amp;#39;maxReceivedMessageSize&amp;#39; and &amp;#39;maxBufferSize&amp;#39; set to their maximum value. In line 12 you configure the service to use the new custom binding. &lt;/p&gt;  &lt;pre class="brush: xml;"&gt;&amp;lt;system.serviceModel&amp;gt;&lt;br /&gt;    &amp;lt;bindings&amp;gt;&lt;br /&gt;        &amp;lt;customBinding&amp;gt;&lt;br /&gt;            &amp;lt;binding name=&amp;quot;CustomBinding_ILargeBufferService&amp;quot;&amp;gt;&lt;br /&gt;                &amp;lt;binaryMessageEncoding /&amp;gt;&lt;br /&gt;                &amp;lt;httpTransport maxReceivedMessageSize=&amp;quot;2147483647&amp;quot; maxBufferSize=&amp;quot;2147483647&amp;quot; /&amp;gt;&lt;br /&gt;            &amp;lt;/binding&amp;gt;&lt;br /&gt;        &amp;lt;/customBinding&amp;gt;&lt;br /&gt;    &amp;lt;/bindings&amp;gt;&lt;br /&gt;    &amp;lt;client&amp;gt;&lt;br /&gt;      &amp;lt;endpoint address=&amp;quot;../Services/LargeBufferService.svc&amp;quot; contract=&amp;quot;LargeBufferService.ILargeBufferService&amp;quot;&lt;br /&gt;          binding=&amp;quot;customBinding&amp;quot; bindingConfiguration=&amp;quot;CustomBinding_ILargeBufferService&amp;quot;&lt;br /&gt;            name=&amp;quot;CustomBinding_ILargeBufferService&amp;quot; /&amp;gt;&lt;br /&gt;    &amp;lt;/client&amp;gt;&lt;br /&gt;&amp;lt;/system.serviceModel&amp;gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;s2.3 &lt;/strong&gt;Open file &amp;#39;web.config&amp;#39; in the &lt;em&gt;Silverlight web project&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;s2.4 &lt;/strong&gt;Modify node &amp;#39;system.serviceModel&amp;#39; to include the following code sample. &lt;/p&gt;

&lt;pre class="brush: xml;"&gt;&amp;lt;system.serviceModel&amp;gt;&lt;br /&gt;    &amp;lt;behaviors&amp;gt;&lt;br /&gt;        &amp;lt;serviceBehaviors&amp;gt;&lt;br /&gt;            &amp;lt;behavior name=&amp;quot;&amp;quot;&amp;gt;&lt;br /&gt;                &amp;lt;serviceMetadata httpGetEnabled=&amp;quot;true&amp;quot; /&amp;gt;&lt;br /&gt;                &amp;lt;serviceDebug includeExceptionDetailInFaults=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;            &amp;lt;/behavior&amp;gt;&lt;br /&gt;        &amp;lt;/serviceBehaviors&amp;gt;&lt;br /&gt;    &amp;lt;/behaviors&amp;gt;&lt;br /&gt;    &amp;lt;bindings&amp;gt;&lt;br /&gt;        &amp;lt;customBinding&amp;gt;&lt;br /&gt;            &amp;lt;binding name=&amp;quot;LargeBufferServiceCustomBinding&amp;quot;&amp;gt;&lt;br /&gt;                &amp;lt;binaryMessageEncoding&amp;gt;&lt;br /&gt;                    &amp;lt;readerQuotas maxArrayLength=&amp;quot;2147483647&amp;quot; /&amp;gt;&lt;br /&gt;                &amp;lt;/binaryMessageEncoding&amp;gt;&lt;br /&gt;                &amp;lt;httpTransport maxReceivedMessageSize=&amp;quot;2147483647&amp;quot; maxBufferSize=&amp;quot;2147483647&amp;quot; /&amp;gt;&lt;br /&gt;            &amp;lt;/binding&amp;gt;&lt;br /&gt;        &amp;lt;/customBinding&amp;gt;&lt;br /&gt;    &amp;lt;/bindings&amp;gt;&lt;br /&gt;    &amp;lt;serviceHostingEnvironment aspNetCompatibilityEnabled=&amp;quot;true&amp;quot;&lt;br /&gt;        multipleSiteBindingsEnabled=&amp;quot;true&amp;quot; /&amp;gt;&lt;br /&gt;    &amp;lt;services&amp;gt;       &lt;br /&gt;      &amp;lt;service name=&amp;quot;WCFLargeBuffer.Web.Services.LargeBufferService&amp;quot;&amp;gt;&lt;br /&gt;          &amp;lt;endpoint address=&amp;quot;&amp;quot; binding=&amp;quot;customBinding&amp;quot; bindingConfiguration=&amp;quot;LargeBufferServiceCustomBinding&amp;quot;&lt;br /&gt;              contract=&amp;quot;WCFLargeBuffer.Web.Services.ILargeBufferService&amp;quot; /&amp;gt;&lt;br /&gt;        &amp;lt;endpoint address=&amp;quot;mex&amp;quot; binding=&amp;quot;mexHttpBinding&amp;quot; contract=&amp;quot;IMetadataExchange&amp;quot; /&amp;gt;&lt;br /&gt;      &amp;lt;/service&amp;gt;&lt;br /&gt;    &amp;lt;/services&amp;gt;&lt;br /&gt;&amp;lt;/system.serviceModel&amp;gt;&lt;/pre&gt;

&lt;p&gt;&lt;u&gt;Where:&lt;/u&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Lines 3-8 – This is the default behavior and most probably already exists in your file. &lt;/li&gt;

  &lt;li&gt;Lines 11-18 – Define a custom binding whose definitions match those we defined in the Silverlight application project. &lt;/li&gt;

  &lt;li&gt;Lines 23-27 – Define the service which should support the large message size. Notice that the &amp;#39;address&amp;#39; attribute is empty. The connection to the service is done by mapping the attributes &amp;#39;name&amp;#39; and &amp;#39;contract&amp;#39; to the concrete implementation of the service and its interface (contract). In line 24&amp;#160; you configure the service to use the binding which was defined in lines 11-18. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h1&gt;Section 3 - Overcoming the exception &amp;#39;&lt;em&gt;HTTP/1.1 415 Unsupported Media Type&amp;#39;&lt;/em&gt; when calling a WCF Silverlight service&lt;/h1&gt;

&lt;p&gt;This exception is a bit tricky since the exception doesn&amp;#39;t indicate the source of the problem. It usually means there&amp;#39;s a problem with the way the service is configured.&amp;#160; If you followed section 2 you should not encounter that problem. The solution of this exception&amp;#160; in Silverlight WCF RIA applications is quite simple. &lt;/p&gt;

&lt;p&gt;When configuring the service in the &amp;#39;web.config&amp;#39; file we set the attribute &amp;#39;address&amp;#39; to be the empty string. This causes Silverlight difficulties in finding the concrete service implementation. This is where conventions come into consideration. You must ensure that the &amp;#39;name&amp;#39; attribute of the service contains the full namespace of the service concrete implementation (class). I formatted the relevant attribute in bold in the provided sample code (line 1).&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;&amp;lt;service name=&amp;quot;&lt;strong&gt;WCFLargeBuffer.Web.Services.LargeBufferService&lt;/strong&gt;&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;endpoint address=&amp;quot;&amp;quot; binding=&amp;quot;customBinding&amp;quot; bindingConfiguration=&amp;quot;LargeBufferServiceCustomBinding&amp;quot;&lt;br /&gt;        contract=&amp;quot;WCFLargeBuffer.Web.Services.ILargeBufferService&amp;quot; /&amp;gt;&lt;br /&gt;  &amp;lt;endpoint address=&amp;quot;mex&amp;quot; binding=&amp;quot;mexHttpBinding&amp;quot; contract=&amp;quot;IMetadataExchange&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;/service&amp;gt;&lt;/pre&gt;

&lt;h1&gt;Article Recap&lt;/h1&gt;

&lt;p&gt;In this article I covered 3 known exceptions which many developers dealt with while developing Silverlight WCF RIA services. In addition this article introduced a way to log WCF for troubleshooting handling in section 1.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://microsoftblog.eransakal.com/wcfLargeBuffer/" target="_blank"&gt;press here to view live example&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Appendix A&lt;/h2&gt;

&lt;p&gt;This is the full listing of the exception handled in section 2:&lt;/p&gt;

&lt;p&gt;“&lt;em&gt;There was an error deserializing the object of type WCFLargeBuffer.Web.Services.DoWorkArgs. The maximum array length quota (16384) has been exceeded while reading XML data. This quota may be increased by changing the MaxArrayLength property on the XmlDictionaryReaderQuotas object used when creating the XML reader. Line 1, position 38134.&amp;#39;.&amp;#160; Please see InnerException for more details.&lt;/em&gt;”&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=905259" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/Web/default.aspx">Web</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/Silverlight4/default.aspx">Silverlight4</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/WCF/default.aspx">WCF</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/RIA/default.aspx">RIA</category></item><item><title>Silverlight PRISM + MVVM - Displaying a dialog to the user - Part 1</title><link>http://blogs.microsoft.co.il/blogs/esakal/archive/2011/09/29/silverlight-prism-mvvm-showing-dialogs-to-the-user.aspx</link><pubDate>Fri, 30 Sep 2011 01:45:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:902205</guid><dc:creator>Eran Sakal</dc:creator><slash:comments>10</slash:comments><comments>http://blogs.microsoft.co.il/blogs/esakal/archive/2011/09/29/silverlight-prism-mvvm-showing-dialogs-to-the-user.aspx#comments</comments><description>&lt;p&gt;&lt;strong&gt;This article applies to the following technologies&lt;/strong&gt;: C#, PRISM 4, Silverlight 4&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/image_27943785.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://blogs.microsoft.co.il/blogs/esakal/image_thumb_20D10835.png" width="354" height="234" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://microsoftblog.eransakal.com/PrismDialogs/" target="_blank"&gt;Press here to view live example&lt;/a&gt; &lt;/p&gt;  &lt;h1&gt;Intro&lt;/h1&gt;  &lt;p&gt;Programmers who don’t use MVVM have easy and affective ways to display a dialog to the user (Message box dialog, confirmation dialog, custom dialog). But what’s the best way to display a dialog with MVVM? In other words: How can one trigger a dialog from the view-model without apathetic to the UI?&lt;/p&gt;  &lt;p&gt;This is how not to do it:&lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;MessageBox.Show(&amp;quot;This is the message&amp;quot;, &amp;quot;This is the title&amp;quot;,MessageBoxButton.OK);&lt;/pre&gt;

&lt;p&gt;The problem with the above code is that the regular MessageBox c# type determines the UI visual and cannot be modified by the view. It will always show a blocking popup. The developer cannot customize the view of the dialog, make it asynced or simulate it for unit tests scenarios.&amp;#160; To code it right you need to de-couple the visual of the dialog from the business logic using the MVVM pattern guidelinces. &lt;/p&gt;

&lt;p&gt;For the sake of simplicity I didn’t trigger any calls to ‘PropertyChanged’ event in code samples shown in the article. Please refer to the demo for obtaining the full code. &lt;/p&gt;

&lt;h2&gt;Demo&lt;/h2&gt;

&lt;p&gt;You can download the demo used in this article from the &lt;a href="http://blogs.microsoft.co.il/blogs/esakal/posts/201109-prismDialogs/PrismMVVMDialogsSample.zip" target="_blank"&gt;following link.&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;Article structure&lt;/h1&gt;

&lt;p&gt;This article is about the following issues:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Section 1 – Displaying a message box to the user. &lt;/li&gt;

  &lt;li&gt;Section 2 - Displaying a confirmation dialog to the user. &lt;/li&gt;

  &lt;li&gt;Section 3 (Part 2) - Changing the visibility of the default message box / confirmation dialog. &lt;/li&gt;

  &lt;li&gt;Section 4 (Part 2) - Displaying a custom dialog (using Child window). &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Article goals&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Use the PRISM framework to show dialogs and interact with the user.&lt;/li&gt;

  &lt;li&gt;De-couple the visual from the logic using MVVM pattern.&lt;/li&gt;

  &lt;li&gt;Avoid using JavaScript objects like&amp;#160; ‘Messagebox’ or ‘Confirmation’. &lt;/li&gt;

  &lt;li&gt;Avoid using 3rd party tools (except for PRISM which is free). &lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Prerequisites&lt;/h1&gt;

&lt;p&gt;Before displaying any dialog you must perform the following.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;p.1 &lt;/strong&gt;If you haven’t done this already, download PRISM 4 from the &lt;a href="http://www.microsoft.com/download/en/details.aspx?id=4922" target="_blank"&gt;following link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;p.2&lt;/strong&gt; Add the following references to the Silverlight project in which you are going to implement the dialog.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;div style="text-align:left;direction:ltr;"&gt;System.Windows.Interactivity.dll (part of .net framework)&lt;/div&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;div style="text-align:left;direction:ltr;"&gt;Microsoft.Expression.Interactions.dll (part of .net framework)&lt;/div&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;div style="text-align:left;direction:ltr;"&gt;Microsoft.Practices.Prism (part of Prism 4)&lt;/div&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;div style="text-align:left;direction:ltr;"&gt;Microsoft.Practices.Prism.Interactivity (part of Prism 4)&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Section 1 – Displaying a message box dialog&lt;/h1&gt;

&lt;p&gt;The following section will demonstrate how to show simple message box dialog to the user. &lt;/p&gt;

&lt;h2&gt;Modifying the view-model&lt;/h2&gt;

&lt;p&gt;In order to display the dialog you will use the type ‘InteractionRequest&amp;lt;Notification&amp;gt;’. This type will be used as proxy between the view-model to the view and will include information about the dialog like title and message. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Coding conventions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;s1.1 &lt;/strong&gt;To adhere to the coding convention ensure that your class name uses the following pattern ‘{View model name}&lt;strong&gt;ViewModel&lt;/strong&gt;’, for example – ‘Users&lt;strong&gt;ViewModel’&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exposing property which represent the dialog&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;s1.2&lt;/strong&gt; Expose a property of type ‘InteractionRequest&amp;lt;Notification&amp;gt;’. Later you will bind the UI popup dialog to this property. Use the following code sample:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;public InteractionRequest&amp;lt;Notification&amp;gt; ShowMessagebox { get; set; }&lt;br /&gt;&lt;/pre&gt;

&lt;p&gt;&lt;u&gt;where&lt;strong&gt;:&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;As mentioned at the beginning of the article – to keep things simple,&amp;#160; I didn’t trigger ‘PropertyChanged’ event&amp;#160; in the code sample. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;s1.3 &lt;/strong&gt;In the view-model constructor, initialize the property with a concrete instance. Use the following code sample:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;ShowMessagebox = new InteractionRequest&amp;lt;Notification&amp;gt;();&lt;br /&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Displaying the dialog when needed&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;s1.4&lt;/strong&gt; Finally, use the following code sample to trigger the display of the dialog to the user:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;ShowMessagebox.Raise(new Notification { Content = &amp;quot;This messagebox was triggered from the ViewModel&amp;quot;, Title = &amp;quot;Nice Title&amp;quot; }, arg =&amp;gt;&lt;br /&gt;{&lt;br /&gt;    // Optional - do something after the user accecpt the messagebox&lt;br /&gt;});&lt;/pre&gt;

&lt;p&gt;&lt;u&gt;Where&lt;strong&gt;:&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The 1st argument (‘Notification’) contains the information that will be displayed to the user. 
    &lt;ul&gt;
      &lt;li&gt;In this example I used a string as the ‘content’. But the content could actually be anything that may eventually be rendered using a data template. &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;

  &lt;li&gt;The 2nd argument (‘Callback’) is optional. Use this callback to execute post handle user interaction after the user closes the dialog. &lt;/li&gt;

  &lt;li&gt;The ‘Notification’ instance that you pass as the first argument will be used as the datacontext of the UI popup. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You just finished modifying the view-model but you still need to modify the view before you can test the code.&lt;/p&gt;

&lt;h2&gt;Modifying the view&lt;/h2&gt;

&lt;p&gt;In this part you are going to add the visual part of the dialog by binding to the property you added to the view-model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Coding conventions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;s1.5 &lt;/strong&gt;To adhere to the coding convention ensure that your class name uses the following pattern ‘{View name}&lt;strong&gt;View&lt;/strong&gt;’&lt;strong&gt;,&lt;/strong&gt; for example – ‘Users&lt;strong&gt;View&lt;/strong&gt;’.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Add required namespaces&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;s1.6&lt;/strong&gt; Add the following namespaces to the xaml:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;xmlns:ei=&amp;quot;http://schemas.microsoft.com/expression/2010/interactivity&amp;quot;    &lt;br /&gt;xmlns:prism=&amp;quot;http://www.codeplex.com/prism&amp;quot;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Add InteractionRequestTrigger behavior&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;s1.7&lt;/strong&gt; The ‘InteractionRequestTrigger’ is used to bind between the view-model exposed property and the visual element in the view.&lt;/p&gt;

&lt;p&gt;Use the following code sample, append it as first child of the grid element ‘LayoutRoot’:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;&amp;lt;ei:Interaction.Triggers&amp;gt;&lt;br /&gt;    &amp;lt;prism:InteractionRequestTrigger SourceObject=&amp;quot;{Binding ShowMessagebox}&amp;quot;&amp;gt;&lt;br /&gt;        &amp;lt;prism:PopupChildWindowAction/&amp;gt;&lt;br /&gt;    &amp;lt;/prism:InteractionRequestTrigger&amp;gt;&lt;br /&gt;&amp;lt;/ei:Interaction.Triggers&amp;gt;&lt;br /&gt;&lt;/pre&gt;

&lt;p&gt;&lt;u&gt;Where&lt;strong&gt;:&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Line 2 – The property ‘SourceObject’ is bound to the property that you exposed in the view-model. In this case ‘ShowMessagebox’ property. &lt;/li&gt;

  &lt;li&gt;Lines 3-5 – Define the visual element which is part of prism framework.&lt;/li&gt;

  &lt;li&gt;Notice – If your xaml already contains ‘Interacation.Triggers’ attached property (line 1) then you should avoid adding another one. Append lines 3-5 to the exists property. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You just finished implementing a message box dialog using PRISM guidelines and MVVM principles. &lt;/p&gt;

&lt;h1&gt;Section 2 – Displaying a confirmation dialog&lt;/h1&gt;

&lt;p&gt;Displaying a confirmation dialog is very similar to the implementation of displaying a messagebox. In this section I will focus on the differences so you should read section 1 before continuing.&lt;/p&gt;

&lt;h2&gt;Modifying the view-model&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Exposing a property which represents the dialog&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;s2.1 &lt;/strong&gt;Expose a property of type ‘InteractionRequest&amp;lt;Confirmation&amp;gt;’. Notice that the generic type is ‘Confirmation” and not ‘Notification’. Use the following code sample:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;public InteractionRequest&amp;lt;Confirmation&amp;gt; ShowConfirmation { get; set; }&lt;br /&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;s2.2 &lt;/strong&gt;In the constructor, initialize the property with a concrete instance. Use the following code sample:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;ShowConfirmation = new InteractionRequest&amp;lt;Confirmation&amp;gt;();&lt;br /&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Displaying the dialog when needed&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;s2.3&lt;/strong&gt; Use the following code sample to trigger the display of the dialog to the user:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;ShowConfirmation.Raise(new Confirmation { Content = &amp;quot;This confirmation dialog was triggered from the ViewModel. Do you accept?&amp;quot;, Title = &amp;quot;Confirmation Title&amp;quot; }, confirmation =&amp;gt;&lt;br /&gt;{&lt;br /&gt;    if (confirmation.Confirmed)&lt;br /&gt;    {&lt;br /&gt;        // User accepted the request (pressed on &amp;#39;ok&amp;#39; button)&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;    {&lt;br /&gt;        // User rejected the request (pressed on &amp;#39;cancel&amp;#39; button)&lt;br /&gt;    }&lt;br /&gt;});&lt;/pre&gt;

&lt;h2&gt;Modifying the view&lt;/h2&gt;

&lt;p&gt;This part is almost identical to the matching part in section 1. The only difference is the property name the ‘SourceObject’ is bound to.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Add required namespaces&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;s2.4&lt;/strong&gt; Add the following namespaces to the xaml:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;xmlns:ei=&amp;quot;http://schemas.microsoft.com/expression/2010/interactivity&amp;quot;    &lt;br /&gt;xmlns:prism=&amp;quot;http://www.codeplex.com/prism&amp;quot;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Add InteractionRequestTrigger behavior&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;s2.5&lt;/strong&gt; Use the following code sample, add it as first child of the grid element ‘LayoutRoot’:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;&amp;lt;ei:Interaction.Triggers&amp;gt;&lt;br /&gt;    &amp;lt;prism:InteractionRequestTrigger SourceObject=&amp;quot;{Binding ShowConfirmation}&amp;quot;&amp;gt;&lt;br /&gt;        &amp;lt;prism:PopupChildWindowAction/&amp;gt;&lt;br /&gt;    &amp;lt;/prism:InteractionRequestTrigger&amp;gt;&lt;br /&gt;&amp;lt;/ei:Interaction.Triggers&amp;gt; &lt;/pre&gt;

&lt;h1&gt;Article recap&lt;/h1&gt;

&lt;p&gt;In this article I demonstrated how to show common dialogs such as messagebox and confirmation. In next article I will focus on more advanced usage such as displaying custom dialogs and style modification. You can download project located at the beginning of the article.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://microsoftblog.eransakal.com/PrismDialogs/" target="_blank"&gt;Press here to view live example&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=902205" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/Silverlight4/default.aspx">Silverlight4</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/MVVM/default.aspx">MVVM</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/PRISM/default.aspx">PRISM</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/UI/default.aspx">UI</category></item><item><title>Silverlight - How to clone any instance of object (including EF entities)</title><link>http://blogs.microsoft.co.il/blogs/esakal/archive/2011/09/01/silverlight-how-to-clone-any-instance-of-object-including-ef-entities.aspx</link><pubDate>Thu, 01 Sep 2011 22:30:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:891259</guid><dc:creator>Eran Sakal</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.microsoft.co.il/blogs/esakal/archive/2011/09/01/silverlight-how-to-clone-any-instance-of-object-including-ef-entities.aspx#comments</comments><description>&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;&lt;strong&gt;מאמר זה רלוונטי לטכנולוגיות הבאות:&lt;/strong&gt; C#, EntityFramework, Silverlight 4&lt;/p&gt;
&lt;h1 style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;הקדמה&lt;/h1&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;מאמר זה מציג דרכים לשכפול של אובייקטים בSilverilght. פעולה כזו נדרשת לא מעט כאשר מתעסקים עם נתונים ורוצים לאפשר למשתמש דרך לשכפל אותם. &lt;/p&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;ראיתי מספר דוגמאות ברשת שבהן מבצעים שכפול ידני (יצירת אובייקט והעתקת כל property בנפרד). הדרכים שמופיעות במאמר זה מראות כיצד ניתן לעשות פעולה זו באופן אוטומטי ובכך לצמצם טעויות אנוש, ליצור קוד נקי וקריא יותר, למנוע קידוד פרטני hardcoded ומימוש פתרון גנרי.&lt;/p&gt;
&lt;h2 style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;מגבלות טכנולוגיות&lt;/h2&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;הדרכים המתוארות במאמר משתמשות בReflection. מטעמי אבטחה חסמו בSilverlight&amp;nbsp; את האפשרות לגשת לPrivate members. המשמעות היא שהאובייקט המשוכפל יהיה זהה לאובייקט המקור בproperties שהם public בלבד. &lt;a href="http://msdn.microsoft.com/en-us/library/stfy7tfc(VS.95).aspx" target="_blank"&gt;קישור להסבר על הגבלה זו בMSDN&lt;/a&gt;. &lt;/p&gt;
&lt;h1 style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;שיטה 1 – שכפול באמצעות DataContractSerializer&lt;/h1&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;בשיטה זו אנחנו עושים שימוש באובייקט DataContractSerializer כדי ליצור את השכפול.&lt;/p&gt;
&lt;h2 style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;הכנה&lt;/h2&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;הוסף רפרנס לקובץ הבא:&lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;
&lt;p&gt;System.Runtime.Serialization.dll&lt;/p&gt;&lt;/div&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;הוסף את הusing הבא בתחילת הקובץ:&lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;
&lt;p&gt;using System.Runtime.Serialization;&lt;/p&gt;&lt;/div&gt;
&lt;h2 style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;קידוד&lt;/h2&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;נגדיר אובייקט מסוג Person. בהמשך המאמר נשתמש באובייקט זה לצורך הדגמה של השיטות.&lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;&lt;pre class="brush: csharp;"&gt;public class Person
{
    public string Name { get; set; }
    public int ChildrenCount { get; set; }        
    public DateTime Birthday { get; set; }

    [IgnoreDataMember]
    public string Comments { get; set; }
}&lt;/pre&gt;&lt;/div&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;השתמש בקוד הבא כדי לשכפל את האובייקט.&lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;&lt;pre class="brush: csharp;"&gt;public T CloneItem&amp;lt;T&amp;gt;(T originalItem) where T:class
{
    T result;
    
    using (var stream = new System.IO.MemoryStream())
    {
        var serializer = new System.Runtime.Serialization.DataContractSerializer(typeof(T));

        // serialize the instance into memory.
        serializer.WriteObject(stream, originalItem);
        stream.Seek(0, System.IO.SeekOrigin.Begin);

        // de-serializing from memory will create new instance 
        result = (T)serializer.ReadObject(stream);                
    }

    return result;
}&lt;/pre&gt;&lt;/div&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;כאשר:&lt;/p&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;
&lt;ul&gt;
&lt;li&gt;השורות הרלוונטיות שמבצעות את העתקה הינן שורות 5-15. &lt;/li&gt;
&lt;li&gt;שורות 10-11 מיצרות העתק של האובייקט בזיכרון&amp;nbsp;(serialization). &lt;/li&gt;
&lt;li&gt;שורה 14 – מייצרת אובייקט חדש באמצעות de-serialization של האובייקט שנשמר בזיכרון בשורות 10-11. &lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;
&lt;p&gt;נקרא למתודה CloneItem כדי לשכפל אובייקט מסוג Person&lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;&lt;pre class="brush: csharp;"&gt;Person originalPerson = new Person { Name = &amp;quot;Eran&amp;quot;, Birthday = new DateTime(1980, 8, 11), Comments = &amp;quot;This will not be copied&amp;quot; };
Person clonedPerson = CloneItem(originalPerson);&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;הערות &lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;שימוש בשיטה זו אפשרי רק החל מ – &lt;span style="DIRECTION:ltr;"&gt;wcf .net 3.5 SP1.&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;שיטה זו מאפשרת העתקה של אובייקטים שיש להם parameterless constructor (ידוע גם כ-default constructor). בלי זה לא יתבצע השכפול. &lt;/li&gt;
&lt;li&gt;שיטה זו מאפשרת גמישות רבה. בזכות השימוש ב-DataContractSerializer ניתן להשפיע על השכפול בעזרת attributes.&amp;nbsp; בשורה 7 במחלקה Person השתמשתי בIgnoreDataMember attribute כדי למנוע העתקה של המאפיין Comments. &lt;/li&gt;&lt;/ul&gt;
&lt;h1&gt;שיטה 2 – שכפול באמצעות Reflection&lt;/h1&gt;
&lt;p&gt;בשיטה זו אנחנו מבצעים שכפול באמצעות Reflection. נחלץ את המאפיינים של אובייקט המקור ונעתיק את תוכנם לאובייקט המשוכפל.&lt;/p&gt;
&lt;h2&gt;הכנה&lt;/h2&gt;
&lt;p&gt;הוסף את הusing הבא בתחילת הקובץ&lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;
&lt;p&gt;using System.Reflection;&lt;/p&gt;&lt;/div&gt;
&lt;h2&gt;קידוד&lt;/h2&gt;
&lt;p&gt;השתמש בקוד הבא כדי לשכפל את האובייקט באמצעות Reflection&lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;&lt;pre class="brush: csharp;"&gt;public T CloneItem&amp;lt;T&amp;gt;(T originalItem, Predicate&amp;lt;string&amp;gt; shouldCloneProperty) where T : class
{
    T result = Activator.CreateInstance&amp;lt;T&amp;gt;();

    foreach (PropertyInfo pi in typeof(T).GetProperties(BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.SetProperty))
    {
        if (shouldCloneProperty == null || shouldCloneProperty(pi.Name))
        {
            pi.SetValue(result, pi.GetValue(originalItem, null), null);
        }
    }

    return result;
}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;כאשר:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;שיטה זו מאפשרת שליטה על השכפול על-ידי predicate שמאפשר להגדיר בזמן ריצה איזה מאפיינים להעתיק. &lt;/li&gt;
&lt;li&gt;שיטה זו לא משתמשת attributes שמודגמים בשיטה 1 ולכן גם המאפיין comments של Person יועתק. &lt;/li&gt;
&lt;li&gt;שורה 3 – שורה זו מייצרת אובייקט מהסוג שרוצים לשכפל.&lt;/li&gt;
&lt;li&gt;שורות 5-11 מבצעות ריצה על מאפיינים של הסוג שמשכפלים ומעתיקה את הערך של כל אחד מהמאפיינים מאובייקט המקור לאובייקט המשוכפל.&lt;/li&gt;
&lt;li&gt;שורה 7 – במידה והוגדר predicate אז המתודה משתמשת בו כדי להחליט אם להעתיק את המאפיין. במידה והועבר null אז כל המאפיינים יועתקו. &lt;/li&gt;&lt;/ul&gt;
&lt;h1&gt;העתקה של Entity ב-Entity Framework&lt;/h1&gt;
&lt;p&gt;שכפול של Entity בEF אפשרי בעזרת 2 השיטות המצויינות למעלה. חשוב לשים לב ל-2 נושאים בהקשר זה:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;צריך לוודא שהרשומה המשוכפלת לא attached לטבלה המקורית. למרות שחשוב להכיר נקודה זו אינך נדרש לבצע פעולה כלשהי. העתקת האובייקט מטפלת בנושא זה באופן עצמאי (בגלל שלא מועתקים private members). &lt;/li&gt;
&lt;li&gt;צריך לאפס את הproperty שמייצג את הprimarykey של הרשומה. האיפוס לא נעשה באופן אוטומטי היות והPrimaryKey הוא public member ולכן יקבל את הערך של האובייקט המקורי.&amp;nbsp; כדי לגרום לEF להתייחס לEntity כרשומה חדשה, אפס את ערך זה בצורה ידנית. לדוגמא - במידה והמפתח הוא מסוג int אז איפוס הערך ל-0 יעשה את העבודה. &lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=891259" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/Web/default.aspx">Web</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/Silverlight4/default.aspx">Silverlight4</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/Entity+Framework/default.aspx">Entity Framework</category></item><item><title>Tip - Bypass runtime exception “Collection was modified; enumeration operation may not execute.”</title><link>http://blogs.microsoft.co.il/blogs/esakal/archive/2011/08/27/tip-_2D00_-bypass-exception-collection-was-modified-enumeration-operation-may-not-execute.aspx</link><pubDate>Sun, 28 Aug 2011 03:30:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:888361</guid><dc:creator>Eran Sakal</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.microsoft.co.il/blogs/esakal/archive/2011/08/27/tip-_2D00_-bypass-exception-collection-was-modified-enumeration-operation-may-not-execute.aspx#comments</comments><description>&lt;p style="text-align:right;direction:rtl;"&gt;&lt;strong&gt;מאמר זה רלוונטי לטכנולוגיות הבאות: &lt;/strong&gt;Silverlight4, asp.net ו-#c.&lt;/p&gt;  &lt;p style="text-align:right;direction:rtl;"&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/exception_50FABC7F.jpg" target="_blank"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="exception" border="0" alt="exception" src="http://blogs.microsoft.co.il/blogs/esakal/exception_thumb_37829378.jpg" width="644" height="274" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;h2 style="text-align:right;direction:rtl;"&gt;הקדמה&lt;/h2&gt;  &lt;p style="text-align:right;direction:rtl;"&gt;השגיאה שמופיעה למעלה קורת כאשר מבצעים ריצה על מערך באמצעות foreach ותוך כדי מוחקים פריט כלשהו מהמערך. פתרון שכיח אך לא אלגנטי לעקיפת השגיאה הוא ליצור מערך חדש ולאגור לתוכו את האובייקטים שרוצים למחוק. לאחר שסיימנו לאגור את האובייקטים צריך לבצע ריצה נוספת ולמחוק אותם מהמערך המקורי. &lt;/p&gt;  &lt;p style="text-align:right;direction:rtl;"&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/badsolution_25E282E0.jpg" target="_blank"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="badsolution" border="0" alt="badsolution" src="http://blogs.microsoft.co.il/blogs/esakal/badsolution_thumb_37063AB6.jpg" width="504" height="281" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p style="text-align:right;direction:rtl;"&gt;פתרון זה אומנם יעבוד אך הוא מכפיל את כמות השורות, יוצר בלאגן בקוד ובשבילי לפחות מרגיז לכתיבה.&lt;/p&gt;  &lt;h2 style="text-align:right;direction:rtl;"&gt;&amp;#160;&lt;/h2&gt;  &lt;h2 style="text-align:right;direction:rtl;"&gt;הפתרון&lt;/h2&gt;  &lt;p style="text-align:right;direction:rtl;"&gt;הפתרון מפתיע בפשטות שלו, כדי לפתור את השגיאה צריך להבין את המקור שלה.&amp;#160; כאשר רצים על מערך בלולאה נעשה שימוש בפקודה yield. פקודה זו מתבצעת מאחורי הקלעים והיא מאפשרת לרוץ על מערך בזמן שהוא נבנה. מחיקת פריט מהמערך תוך שרצים על המערך גורמת לשגיאה.&amp;#160; אם אתה מעוניין לקרוא עוד על yield תכנס &lt;a href="http://www.ytechie.com/2009/02/using-c-yield-for-readability-and-performance.html" target="_blank"&gt;לקישור הבא&lt;/a&gt;. &lt;/p&gt;  &lt;p style="text-align:right;direction:rtl;"&gt;כדי לעקוף את הבעיה נשתמש ב-extended method שנקראת ToList וניתן למצוא אותה ב-namespace שנקרא&amp;#160; System.Linq.&lt;/p&gt;  &lt;p style="text-align:right;direction:rtl;"&gt;&amp;#160;&lt;/p&gt;  &lt;div style="text-align:left;direction:ltr;"&gt;   &lt;pre class="brush: csharp;"&gt;// put this in the beginning of the file (with all the other ‘using’ statements)  
using System.Linq;

// execute foreach on a list by calling method &amp;#39;ToList&amp;#39; on the original list
foreach (ImportedExpanse expanse in expanses.ToList())
{
    if (expanse.BillAmount &amp;lt;= 0)
    {
        expanses.Remove(expanse);                        
    }
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p style="text-align:right;direction:rtl;"&gt;&lt;/p&gt;

&lt;p style="text-align:right;direction:rtl;"&gt;&lt;/p&gt;

&lt;p style="text-align:right;direction:rtl;"&gt;&lt;/p&gt;

&lt;p style="text-align:right;direction:rtl;"&gt;כאשר:&lt;/p&gt;

&lt;div style="text-align:right;direction:rtl;"&gt;
  &lt;ul&gt;
    &lt;li&gt;שורה 2 – בפתרון זה אנחנו משתמשים בextended method. כדי שאפשר יהיה לקרוא לה חייבים שיהיה לנו using ל-System.Linq. &lt;/li&gt;

    &lt;li&gt;שורה 5 – לאחר הגרדרת ה- using ניתן לקרוא למתודה ToList. שורה זו גורמת&amp;#160; לforeach לרוץ על מערך ולא להשתמש במנגנון ה-yield ולכן פעולת המחיקה לא פוגעת בריצה של הלולאה. &lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;

&lt;div style="text-align:right;direction:rtl;"&gt;
  &lt;p&gt;&amp;#160;&lt;/p&gt;

  &lt;h2&gt;קישורים חיצוניים&lt;/h2&gt;

  &lt;ul&gt;
    &lt;li&gt;&lt;a href="http://www.ytechie.com/2009/02/using-c-yield-for-readability-and-performance.html" target="_blank"&gt;קישור&lt;/a&gt; – הסבר פשוט וברור כיצד פועל מנגנון yield. &lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=888361" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/Tips/default.aspx">Tips</category></item><item><title>Silverlight – TreeView control kick-start</title><link>http://blogs.microsoft.co.il/blogs/esakal/archive/2011/08/23/silverlight-treeview-control-kick-start.aspx</link><pubDate>Tue, 23 Aug 2011 23:30:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:886876</guid><dc:creator>Eran Sakal</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.microsoft.co.il/blogs/esakal/archive/2011/08/23/silverlight-treeview-control-kick-start.aspx#comments</comments><description>&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;
&lt;p&gt;&lt;strong&gt;מאמר זה רלוונטי לטכנולוגיות הבאות: Silverlight4&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/posts/TreeViewBasics.zip" target="_blank"&gt;לחץ כאן להורדת קוד לדוגמא של המאמר&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/treeview20_44B078F3.jpg" target="_blank"&gt;&lt;img style="BACKGROUND-IMAGE:none;BORDER-RIGHT-WIDTH:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;BORDER-TOP-WIDTH:0px;BORDER-BOTTOM-WIDTH:0px;BORDER-LEFT-WIDTH:0px;PADDING-TOP:0px;" title="treeview20" border="0" alt="treeview20" src="http://blogs.microsoft.co.il/blogs/esakal/treeview20_thumb_277AAB1C.jpg" width="304" height="242" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;הקדמה&lt;/h2&gt;
&lt;p&gt;במידה ורוצים להציג נתונים עם קשרים היררכים משתמשים בפקד מסוג TreeView. פקד זה מגיע כחלק מ-silverlight. במאמר זה אציג את הצעדים הנדרשים לשימוש בסיסי בפקד. במאמר הבא אראה כיצד ניתן להתאים אותו לעבודה עם MVVM Pattern.&lt;/p&gt;
&lt;h2&gt;חלק 1 - הוספת פקד מסוג TreeView&lt;/h2&gt;
&lt;p&gt;בדוגמא הבאה נגדיר מבנה נתונים בסיסי, נוסיף פקד מסוג TreeView למסך ונציג את הנתונים בעזרת הפקד שיצרנו.&lt;/p&gt;
&lt;h3&gt;הכנת הפרויקט&lt;/h3&gt;
&lt;p&gt;צור פרוייקט מסוג Silverlight Application. &lt;/p&gt;
&lt;p&gt;הוסף רפרנס לקובץ בשם:&lt;/p&gt;
&lt;p style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;System.Windows.Controls.dll&lt;/p&gt;
&lt;h3&gt;קובץ MainPage.xaml&lt;/h3&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;
&lt;p&gt;פתח את MainPage.xaml. הוסף הגדרה עבור ה-namespaces הבאים בתחילת הקובץ.&lt;/p&gt;
&lt;p style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;xmlns:controls=&amp;quot;clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;xmlns:dataHierarcy=&amp;quot;clr-namespace:System.Windows;assembly=System.Windows.Controls&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;כאשר:&lt;/p&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;
&lt;ul&gt;
&lt;li&gt;הנתיב הראשון מכיל את הפקד TreeView &lt;/li&gt;
&lt;li&gt;הנתיב השני מכיל את הפקד “HierarchicalDataTemplate”. בעזרת פקד זה נגדיר את הקשר בין הקטגוריה לתת-קטגוריות. &lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;
&lt;p&gt;כעת ניתן להוסיף את הפקד. העתק את הקוד הבא לתוך ה-XAML.&lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;&lt;pre class="brush: xml;"&gt;&amp;lt;Grid x:Name=&amp;quot;LayoutRoot&amp;quot; Background=&amp;quot;White&amp;quot;&amp;gt;
    &amp;lt;StackPanel&amp;gt;
        &amp;lt;controls:TreeView x:Name=&amp;quot;mainTreeView&amp;quot;&amp;gt;
            &amp;lt;controls:TreeView.ItemTemplate&amp;gt;
                &amp;lt;dataHierarcy:HierarchicalDataTemplate ItemsSource=&amp;quot;{Binding Children}&amp;quot;&amp;gt;                    
                    &amp;lt;TextBlock Text=&amp;quot;{Binding Name}&amp;quot;&amp;gt;&amp;lt;/TextBlock&amp;gt;                    
                &amp;lt;/dataHierarcy:HierarchicalDataTemplate&amp;gt;                
            &amp;lt;/controls:TreeView.ItemTemplate&amp;gt;
        &amp;lt;/controls:TreeView&amp;gt;
    &amp;lt;/StackPanel&amp;gt;
&amp;lt;/Grid&amp;gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;כאשר:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;שורה 1 – הפקד שמופיע בשורה זו אמור להיות כבר בקובץ. העתק לתוכו את שורות 2-10. &lt;/li&gt;
&lt;li&gt;שורות 5-7 – בשורות אלו אנחנו מגדירים את התבנית שבאמצעותה יוצגו הנתונים. התבנית מסוג “HierarchicalDataTemplate” מאפשרת הגדרת קשר של קטגוריה ל-תת קטגוריות. בדוגמה זו אנחנו מגדירים שהתת-קטגוריות של האובייקט נמצאות במאפיין Children.&amp;nbsp; &lt;/li&gt;
&lt;li&gt;שורה 6 –&amp;nbsp; בשורה זו הגדרנו את התבנית הויזואלית של הקטגוריות ותת-הקטגוריות (מדובר באותה תבנית). במקרה שלנו מדובר בתבנית פשוטה שבה אנחנו מציגים את התוכן של המאפיין “Name”. &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;סיימנו עם הUI, עכשיו נעבור להגדרת מבנה הנתונים.&lt;/p&gt;
&lt;h3&gt;קובץ CategoryItem.cs&lt;/h3&gt;
&lt;p&gt;צור קובץ בשם CategoryItem.cs והעתק לתוכו את הקוד הבא:&lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;&lt;pre class="brush: csharp;"&gt;public class CategoryItem
    {
        public string Name { get; set; }
        public List&amp;lt;CategoryItem&amp;gt; Children { get; set; }
        public bool IsNew { get; set; }
        
        public CategoryItem(string name, params CategoryItem[] children)
        {
            this.Name = name;
            this.IsNew = false;
            this.Children = new List&amp;lt;CategoryItem&amp;gt;(children);
        }

        public CategoryItem(string name, bool isNew, params CategoryItem[] children)
        {
            this.Name = name;
            this.IsNew = isNew;
            this.Children = new List&amp;lt;CategoryItem&amp;gt;(children);
        }
    }&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;קובץ MainPage.xaml.cs&lt;/h3&gt;
&lt;p&gt;פתח את הקובץ MainPage.xaml.cs. העתק את הקוד הבא:&lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;&lt;pre class="brush: csharp;"&gt;public partial class MainPage : UserControl
{
    public MainPage()
    {
        InitializeComponent();

        mainTreeView.ItemsSource = createCategoriesData();            
    }

    private System.Collections.IEnumerable createCategoriesData()
    {
        List&amp;lt;CategoryItem&amp;gt; result = new List&amp;lt;CategoryItem&amp;gt;()
        {
            new CategoryItem(&amp;quot;Mobiles&amp;quot;, 
                new CategoryItem(&amp;quot;Apple&amp;quot;,
                    new CategoryItem(&amp;quot;Iphone 4&amp;quot;),
                    new CategoryItem(&amp;quot;Iphone 5&amp;quot;,true)),
                new CategoryItem(&amp;quot;Samsung&amp;quot;,
                    new CategoryItem(&amp;quot;Galaxy S1&amp;quot;),
                    new CategoryItem(&amp;quot;Galaxy S2&amp;quot;,true))),
            new CategoryItem(&amp;quot;Tablets&amp;quot;, 
                new CategoryItem(&amp;quot;Asus&amp;quot;,
                    new CategoryItem(&amp;quot;Asus Transformer&amp;quot;)),
                new CategoryItem(&amp;quot;Acer&amp;quot;)
            )                
        };

        return result;            
    }
}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;כאשר:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;המחלקה שמייצגת את מבנה הנתונים “CategoryItem” יכולה להכיל מאפיינים רבים נוספים. ניתן לעשות Binding למאפיינים אלו דרך הפקד. &lt;/li&gt;
&lt;li&gt;שורה 7 - בדוגמא זו השתמשתי בצורה “פשוטה” של העברת מבנה הנתונים לפקד. עשיתי זאת&amp;nbsp; כדי לפשט את הדוגמא. ביצעתי פניה ל&amp;#39;”ItemSource” ב-Constructor לצורך איתחול הנתונים. &lt;/li&gt;
&lt;li&gt;שורה 10 – יוצרת מבנה נתונים סטטי. באפליקציות אמיתיות הנתונים יטענו ממקור נתונים. במאמר הבא אראה כיצד ניתן ליצור מבנה נתונים היררכי מתוך טבלה בבסיס הנתונים (שהיא שטוחה כברירת מחדל). &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;סיימנו. הרץ את הפרוייקט. אתה אמור לראות משהו שנראה כך:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/treeview10_450C861B.jpg" target="_blank"&gt;&lt;img style="BACKGROUND-IMAGE:none;BORDER-RIGHT-WIDTH:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;BORDER-TOP-WIDTH:0px;BORDER-BOTTOM-WIDTH:0px;BORDER-LEFT-WIDTH:0px;PADDING-TOP:0px;" title="treeview10" border="0" alt="treeview10" src="http://blogs.microsoft.co.il/blogs/esakal/treeview10_thumb_531B4F4B.jpg" width="304" height="242" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;חלק 2 – ביצוע פעולות נוספות על הפקד TreeView&lt;/h2&gt;
&lt;p&gt;סעיף זה מכיל תיאור לא מפורט של פעולות שכיחות שעושים עם הפקד TreeView.&lt;/p&gt;
&lt;h3&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3&gt;ביצוע פעולות על הפריט הנבחר באמצעות קוד&lt;/h3&gt;
&lt;p&gt;לצורך קבלת הפריט הנבחר בצע קריאה למאפיין “SelectedItem”. &lt;/p&gt;
&lt;h3&gt;קבלת אובייקט TreeViewItem עבור אובייקט ממערך הנתונים&lt;/h3&gt;
&lt;p&gt;הפקד TreeView מייצר אובייקט מסוג TreeViewItem עבור כל אובייקט במבנה הנתונים שאנחנו מעבירים. דרך אובייקט זה ניתן לבצע פעולות כמו להרחיב את הפריט (מאפיין IsExpanded), להשפיע על העיצוב שלו ועוד. &lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;&lt;pre class="brush: csharp;"&gt;mainTreeView.UpdateLayout();

TreeViewItem treeViewItem = mainTreeView.ItemContainerGenerator.ContainerFromItem(mainTreeView.SelectedItem) as TreeViewItem;

if (treeViewItem != null)
{                                
    // do what you want
}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;כאשר:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;שורה 1 – נועדה להבטיח שהתצוגה של העץ עדכנית. מבלי להכנס לסיבה אובייקט זה לא יווצר במידה והעץ לא מציג את הנתון המבוקש. &lt;/li&gt;
&lt;li&gt;שורה 3 – אנחנו משתמשים במאפיין “ItemContainerGenerator” לביצוע ההמרה. &lt;/li&gt;
&lt;li&gt;שורה 5 – חשוב תמיד לבצע בדיקה שהאובייקט חזר. יש מספר סיבות עבורן האובייקט יכול לא לחזור: 
&lt;ul&gt;
&lt;li&gt;האובייקט המבוקש לא קיים או לא מוצג על המסך. &lt;/li&gt;
&lt;li&gt;הפקד עדיין לא נטען, משמע ביצעתם את הפעולה לפני שהאירוע “Loaded” של הפקד נזרק. &lt;/li&gt;
&lt;li&gt;האובייקט מוצג על המסך אבל התצוגה עדיין לא התעדכנה. לצורך כך אנחנו מבצעים קריאה ל”UpdateLayout” בשורה 1 &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;h3&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3&gt;רישום לאירוע כשהמשתמש בוחר פריט בפקד&lt;/h3&gt;
&lt;p&gt;לצורך קבל חיווי כשהמשתמש מחליף את הפריט הנבחר הרשם לאירוע”SelectedItemChanged”.&lt;/p&gt;
&lt;h3&gt;עיצוב שונה בין רמות שונות בעץ&lt;/h3&gt;
&lt;p&gt;כדי ליצור עיצוב שונה בין הפריטים ברמה הראשונה לבין התת-פריטים נעזר בדוגמא הבאה. החלף את הקוד בXAML עם הקוד הבא:&lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;&lt;pre class="brush: xml;"&gt;&amp;lt;controls:TreeView x:Name=&amp;quot;mainTreeView&amp;quot;&amp;gt;
    &amp;lt;controls:TreeView.ItemTemplate&amp;gt;
        &amp;lt;dataHierarcy:HierarchicalDataTemplate ItemsSource=&amp;quot;{Binding Children}&amp;quot;&amp;gt;
            &amp;lt;dataHierarcy:HierarchicalDataTemplate.ItemTemplate&amp;gt;
                &amp;lt;DataTemplate&amp;gt;
                    &amp;lt;TextBlock FontStyle=&amp;#39;Italic&amp;#39; Text=&amp;#39;{Binding Path=Name}&amp;#39; /&amp;gt;
                &amp;lt;/DataTemplate&amp;gt;
            &amp;lt;/dataHierarcy:HierarchicalDataTemplate.ItemTemplate&amp;gt;
            
            &amp;lt;TextBlock Text=&amp;#39;{Binding Path=Name}&amp;#39; FontWeight=&amp;#39;Bold&amp;#39; /&amp;gt;
        &amp;lt;/dataHierarcy:HierarchicalDataTemplate&amp;gt;
    &amp;lt;/controls:TreeView.ItemTemplate&amp;gt;
&amp;lt;/controls:TreeView&amp;gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;כאשר:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;בדוגמא זו הפריטים ברמה 1 יוצגו כשהם מודגשים ושאר תתי-הפריטים יוצגו כשהם מוטים (תצלום מסך מצורף בהמשך) &lt;/li&gt;
&lt;li&gt;שורות 4-8 – בשורות אלו הגדרנו את המאפיין “ItemTemplate” של הפקד “HierarchicalDataTemplate”. מאפיין זה מכיל את התבנית שבה יוצגו התת-פריטים. &lt;/li&gt;
&lt;li&gt;שורה 10 – בשורה זו הגדרנו את התבנית שבה יוצג הפריט הנוכחי. &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;לאחר הרצת הקוד מחדש האפליקציה אמורה להראות כך:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/treeview20_338BFF76.jpg" target="_blank"&gt;&lt;img style="BACKGROUND-IMAGE:none;BORDER-RIGHT-WIDTH:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;BORDER-TOP-WIDTH:0px;BORDER-BOTTOM-WIDTH:0px;BORDER-LEFT-WIDTH:0px;PADDING-TOP:0px;" title="treeview20" border="0" alt="treeview20" src="http://blogs.microsoft.co.il/blogs/esakal/treeview20_thumb_484DD229.jpg" width="304" height="242" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;לסיכום&lt;/h2&gt;
&lt;p&gt;במאמר זה ראינו כיצד להציג נתונים היררכים באמצעות פקד מסוג TreeView. לצערי הפקד שמגיע עם silverlight מוגבל ביכולות ומקשה על שילובו באפליקציות עסקיות ובמיוחד באפליקציות שמפותחות לפי עקרונות MVVM. במאמר הבא אני אראה כיצד ניתן להתאים אותו לשימוש באפליקציות MVVM.&lt;/p&gt;
&lt;h3&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/posts/TreeViewBasics.zip" target="_blank"&gt;לחץ כאן להורדת קוד לדוגמא של המאמר&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;u&gt;קישורים חיצוניים:&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.silverlight.net/blogs/justinangel/archive/2008/11/18/silverlight-toolkit-treeview-treeviewitem-amp-hierarchaldatatemplate.aspx" target="_blank"&gt;קישור 1 (אנגלית)&lt;/a&gt; – קישור זה מכיל מדריך בסיסי מקיף לשימוש ב-TreeView. המדריך מראה כיצד ניתן ליצור את הפקד באמצעות “Expression Blend”, כיצד לשנות את הstyle של הפקד ועוד.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://silverlightfeeds.com/post/543/Silverlight_TreeView_Advanced_Scenarios_TreeViewExtended.aspx" target="_blank"&gt;קישור 2 (אנגלית)&lt;/a&gt; – מדריך לביצוע פעולות מתקדמות כגון מציאת TreeViewItem עבור אובייקט מידע, הקשבה ללחיצה עם העכבר על פריט ועוד.&lt;/p&gt;&lt;/div&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=886876" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/Silverlight4/default.aspx">Silverlight4</category></item><item><title>Delegates in daily use - Part I</title><link>http://blogs.microsoft.co.il/blogs/esakal/archive/2010/09/26/delegates-in-daily-use-part-i.aspx</link><pubDate>Mon, 27 Sep 2010 00:01:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:716136</guid><dc:creator>Eran Sakal</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.microsoft.co.il/blogs/esakal/archive/2010/09/26/delegates-in-daily-use-part-i.aspx#comments</comments><description>&lt;div dir="rtl" align="right"&gt; &lt;p&gt;למרות שהרבה אנשים מכירים את המושג Event המתבסס על delegates, המושג delegate פחות שכיח. אנשים אומנם שמעו על המושג אבל לא בהכרח יודעים מה זה, איך עובדים עם זה והכי חשוב - איך זה יכול לשרת אותנו בפיתוח. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;u&gt;תוכן המאמר&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt; &lt;div align="right"&gt;delegate – הגדרה כללית&lt;/div&gt; &lt;li&gt; &lt;div align="right"&gt;שימוש מבחינת syntax&lt;/div&gt; &lt;li&gt; &lt;div align="right"&gt;דוגמאות בסיסיות לצורך הבנה.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt; &lt;h1&gt;הגדרה כללית&lt;/h1&gt; &lt;p dir="rtl" align="right"&gt;delegate הינו אובייקט שעוטף מתודה. את הdelegate ניתן להעביר בתור פרמטר למתודות אחרות או להגדיר כproperty של אובייקט. בכל שלב שהוא ניתן להריץ את המתודה באמצעות פניה לdelegate מבלי לדעת איזו מתודה רצה בפועל. &lt;/p&gt; &lt;p dir="rtl" align="right"&gt;לצורך הדוגמא נסתכל על כפתור בממשק גרפי. כאשר לוחצים על כפתור אנחנו רוצים שתופעל לוגיקה כלשהי. במילים אחרות אנחנו רוצים שבלחיצה על כפתור תורץ מתודה ספציפית. מה הבעיה? שהכפתור לא מכיר את המתודה שאנחנו רוצים להריץ. בדיוק למצב זה קיים delegate. כל מה שצריך לעשות זה ליצור כפתור ולהעביר אליו את המתודה שרוצים שתרוץ לאחר לחיצה.&lt;/p&gt; &lt;h2 align="right"&gt;Syntax – כיצד מגדירים בקוד&lt;/h2&gt; &lt;p dir="rtl" align="right"&gt;את ה-delegate מגדירים בדומה לחתימה של מתודה ללא תוכן. &lt;/p&gt; &lt;div dir="ltr" align="left"&gt; &lt;blockquote&gt; &lt;p&gt;[scope] &lt;strong&gt;delegate &lt;/strong&gt;[return-type]&lt;b&gt; delegateName&lt;/b&gt; ([parameters]);&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt; &lt;p dir="rtl" align="right"&gt;כאשר:&lt;/p&gt; &lt;blockquote dir="rtl"&gt; &lt;p dir="rtl" align="right"&gt;&lt;strong&gt;[scope]&lt;/strong&gt; – (אופציונלי). הגדרת רמת החשיפה של הdelegate (ערכים אפשריים private / protected / public / internal). &lt;br /&gt;&lt;strong&gt;[return-type]&lt;/strong&gt; – מתודה שרוצים להעביר לdelegate זה חייבת להחזיר את הערך הזה.&lt;br /&gt;&lt;strong&gt;[parameters]&lt;/strong&gt; – מתודה שרוצים להעביר לdelegate זה חייבת לקבל את פרמטרים אלו לפי סדר.&lt;/p&gt;&lt;/blockquote&gt; &lt;p dir="rtl" align="right"&gt;הערות:&lt;/p&gt; &lt;div dir="rtl" align="right"&gt; &lt;ul&gt; &lt;li&gt;שים לב למילה השמורה delegate לפיה יודע הCLR כי מדובר בהגדרה של delegate ולא במתודה רגילה.  &lt;li&gt;את הdelegate ניתן להגדיר באופן ישיר מתחת לnamespace או כחלק מהגדרה של מחלקה. &lt;/li&gt;&lt;/ul&gt;&lt;/div&gt; &lt;h3 align="right"&gt;דוגמאות&lt;/h3&gt; &lt;div dir="rtl" align="right"&gt; &lt;div style="border-bottom:silver 1px solid;text-align:left;border-left:silver 1px solid;padding-bottom:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;padding-left:4px;width:97.5%;padding-right:4px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;height:33px;max-height:200px;font-size:8pt;overflow:auto;border-top:silver 1px solid;cursor:text;border-right:silver 1px solid;padding-top:4px;" id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;delegate&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; LogDelegate(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; content);&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p dir="rtl" align="right"&gt;בדוגמא זו הגדרנו delegate בשם &amp;quot;LogDelegate&amp;quot;. נהוג להוסיף את המילה &amp;quot;Delegate&amp;quot; בסוף השם לצורך קריאות. בעזרת delegate זה ניתן להעביר מתודות שלא מחזירה כלום (void) ומקבלות פרמטר אחד מסוג string. &lt;/p&gt;
&lt;div dir="rtl" align="right"&gt;
&lt;div style="border-bottom:silver 1px solid;text-align:left;border-left:silver 1px solid;padding-bottom:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;padding-left:4px;width:97.5%;padding-right:4px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;height:39px;max-height:200px;font-size:8pt;overflow:auto;border-top:silver 1px solid;cursor:text;border-right:silver 1px solid;padding-top:4px;" id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;height:24px;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;delegate&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; TryFormatNumberDelegate(&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; number, &lt;span style="color:#0000ff;"&gt;out&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; formatterNumber);&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p dir="rtl" align="right"&gt;בדוגמא זו הגדרנו delegate בשם &amp;quot;TryFormatNumberDelegate&amp;quot;.&amp;nbsp; בעזרת delegate זה ניתן להעביר מתודות שמחזירות ערך bool ומקבלות פרמטר מסוג int ופרמטר מסוג out string.&amp;nbsp; &lt;/p&gt;
&lt;h2&gt;איך יודעים איזו מתודה מתאימה לdelegate&lt;/h2&gt;
&lt;p&gt;ניתן להעביר מתודה למשתנה מסוג delegae כלשהו רק במידה והחתימה של המתודה ושל הdelegate זהים. משמע: ה-return type, מספר הפרמטרים שהמתודה מקבלת והסוג של הפרמטרים זהים לאלו של ה-delegate.&lt;/p&gt;
&lt;h2&gt;מי בודק אם העברנו מתודה מתאימה?&lt;/h2&gt;
&lt;p&gt;במידה ולא העברנו מתודה מסוג מתאים לdelegate הקוד לא יעבור קומפיליציה - מכאן שאתם לא יכולים לטעות. תזמון הבדיקה אינו מקרי וזאת היות ובזמן ריצה הקוד שמקבל מצביע למתודה מסתמך על כך שהוא איזה פרמטרים צריך להעביר ואיזה ערך היא מחזירה.&lt;/p&gt;
&lt;h1&gt;שימוש בdelegate&lt;/h1&gt;
&lt;p dir="rtl" align="right"&gt;לאחר שהגדרנו delegate בקוד ניתן להשתמש בו כמו סוגים אחרים של אובייקטים שאנחנו מכירים – string, int, DateTime. את הdelegate ניתן להגדיר כמשתנה במתודה, כפרמטר של מתודה או מאפיין של מחלקה. &lt;/p&gt;
&lt;p dir="rtl" align="right"&gt;נסתכל על הדוגמא הבאה. בדוגמא זו יצרנו מחלקה &amp;quot;FileHandler&amp;quot; שמקבלת נתיב לקובץ, קוראת את התוכן שלו ומריצה לוגיקה שהועברה לה ב-delegate בלי לדעת מה הלוגיקה עושה.&lt;/p&gt;
&lt;p dir="rtl" align="right"&gt;&amp;nbsp;&lt;/p&gt;
&lt;div dir="rtl" align="right"&gt;
&lt;div style="border-bottom:silver 1px solid;text-align:left;border-left:silver 1px solid;padding-bottom:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;padding-left:4px;width:97.5%;padding-right:4px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;max-height:200px;font-size:8pt;overflow:auto;border-top:silver 1px solid;cursor:text;border-right:silver 1px solid;padding-top:4px;" id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; FileHandler&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum3"&gt;   3:&lt;/span&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;delegate&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; HandleContentDelegate(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; content);&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum4"&gt;   4:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum5"&gt;   5:&lt;/span&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; HandleFile(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; filePath, HandleContentDelegate handleContentMethod)&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum6"&gt;   6:&lt;/span&gt;    {&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum7"&gt;   7:&lt;/span&gt;        &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (File.Exists(filePath))&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum8"&gt;   8:&lt;/span&gt;        {&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum9"&gt;   9:&lt;/span&gt;            &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; content = File.ReadAllText(filePath);&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum10"&gt;  10:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum11"&gt;  11:&lt;/span&gt;            &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (handleContentMethod != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum12"&gt;  12:&lt;/span&gt;            {&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum13"&gt;  13:&lt;/span&gt;                handleContentMethod(content);&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum14"&gt;  14:&lt;/span&gt;            }&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum15"&gt;  15:&lt;/span&gt;        }&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum16"&gt;  16:&lt;/span&gt;    }&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum17"&gt;  17:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p dir="rtl" align="right"&gt;הסבר קוד:&lt;/p&gt;
&lt;div dir="rtl" align="right"&gt;
&lt;ul&gt;
&lt;li&gt;שורה 3 – בשורה זו הגדרנו delegate בשם &amp;quot;HandleContentDelegate&amp;quot; שמתאים לכל מתודה שלא מחזירה כלום (void) ומקבלת string כפרמטר יחיד. 
&lt;li&gt;שורות 5 עד 16 – מגדירות מתודה בשם &amp;quot;HandleFile&amp;quot;. מתודה זו מקבלת פרמטר &amp;quot;filePath&amp;quot; (נתיב לקובץ), קוראת את התוכן של הקובץ ומעבירה את התוכן למתודה שהועברה בפרמטר &amp;quot;handleContentMethod&amp;quot;. שימו לב שבגלל שאנחנו מכירים את החתימה של הdelegate אנחנו יודעים בוודאות שהמתודה צריכה לקבל מחרוזת ולא להחזיר ערך. מכאן שלא באמת רלוונטי עבורנו איזו מתודה הועברה לdelegate.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;
&lt;p dir="rtl" align="right"&gt;הערות והבהרות:&lt;/p&gt;
&lt;div dir="rtl" align="right"&gt;
&lt;ul&gt;
&lt;li&gt;שורה 13 – מבצעת קריאה לdelegate. בפועל מתבצעת קריאה למתודה שהועברה בתור פרמטר. שימו לב שקריאה לdelegate נעשית בדיוק כפי שקוראים למתודה. 
&lt;li&gt;בקוד זה אני מדגים קונבנציה שכיחה של שמות (לא חובה אבל מומלץ): 
&lt;ul&gt;
&lt;li&gt;שורה 3 - שם הdelegate מסתיים במילה &amp;quot;Delegate&amp;quot; 
&lt;li&gt;שורה 5 - פרמטר מסוג delegate מסתיים עם המילה &amp;quot;Method&amp;quot;. &lt;/li&gt;&lt;/ul&gt;
&lt;li&gt;שורה 11 – לפני שאנחנו קוראים לפרמטר מסוג delegate חשוב לבדוק שהוא מכיל מתודה כלשהי ולא שווה לnull. זאת היות ומדובר בreference type. &lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;
&lt;p dir="rtl" align="right"&gt;הדוגמא הבאה מראה שימוש בFileHandler שכתבנו בדוגמא הקודמת.&amp;nbsp; בדוגמא זו אנחנו קוראים פעמיים לFileHandler. פעם אחת אנחנו מעבירים מתודה שמציגה את התוכן של הקובץ על המסך ופעם שניה מציגה אותו בחלון DEBUG שבVisual Studio. שימו לב שהמחלקה FileHandler נכתבה בלי לדעת את הלוגיקה שתורץ בתוכה. &lt;/p&gt;&lt;strong&gt;&lt;/strong&gt;
&lt;div dir="rtl" align="right"&gt;
&lt;div style="border-bottom:silver 1px solid;text-align:left;border-left:silver 1px solid;padding-bottom:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;padding-left:4px;width:97.5%;padding-right:4px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;max-height:200px;font-size:8pt;overflow:auto;border-top:silver 1px solid;cursor:text;border-right:silver 1px solid;padding-top:4px;" id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; Test&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum3"&gt;   3:&lt;/span&gt;   &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; DisplayOnScreen(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; messageToShow)&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum4"&gt;   4:&lt;/span&gt;   {&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum5"&gt;   5:&lt;/span&gt;       MessageBox.Show(messageToShow);&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum6"&gt;   6:&lt;/span&gt;   }&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum7"&gt;   7:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum8"&gt;   8:&lt;/span&gt;   &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; DisplayOnImmediate(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; messageToShow)&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum9"&gt;   9:&lt;/span&gt;   {&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum10"&gt;  10:&lt;/span&gt;       System.Diagnostics.Debug.Write(messageToShow);&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum11"&gt;  11:&lt;/span&gt;   }&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum12"&gt;  12:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum13"&gt;  13:&lt;/span&gt;   &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Execute()&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum14"&gt;  14:&lt;/span&gt;   {            &lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum15"&gt;  15:&lt;/span&gt;       &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; filePath = &lt;span style="color:#006080;"&gt;@&amp;quot;c:\test.txt&amp;quot;&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum16"&gt;  16:&lt;/span&gt;       FileHandler fileHandler = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; FileHandler();&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum17"&gt;  17:&lt;/span&gt;       &lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum18"&gt;  18:&lt;/span&gt;       fileHandler.HandleFile(filePath, DisplayOnScreen);&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum19"&gt;  19:&lt;/span&gt;       fileHandler.HandleFile(filePath, &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.DisplayOnImmediate);&lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum20"&gt;  20:&lt;/span&gt;   }                 &lt;/pre&gt;&lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum21"&gt;  21:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p dir="rtl" align="right"&gt;הסבר קוד: &lt;/p&gt;
&lt;div dir="rtl" align="right"&gt;
&lt;ul&gt;
&lt;li&gt;שורה 13 – המתודה &amp;quot;Execute&amp;quot;&amp;nbsp; – קוראת לFileHandler פעמיים. 
&lt;ul&gt;
&lt;li&gt;בשורה 18 - מעבירה כפרמטר את המתודה DisplayOnScreen. 
&lt;li&gt;בשורה 19 - מעבירה כפרמטר את המתודה ShowAsOutput. &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;
&lt;h1&gt;שאלות-תשובות&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;שאלה&lt;br /&gt;&lt;/strong&gt;האם שמות הפרמטרים חייבים להיות זהים במתודה ובdelegate? &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;תשובה &lt;br /&gt;&lt;/strong&gt;לא. הפרמטר הראשון בdelegate נקרא &amp;quot;content&amp;quot; ואנחנו מעבירים מתודות בשורות 18 ו-19, שהפרמטר הראשון שלה נקרא &amp;quot;messageToShow&amp;quot;. זה מצב תקין היות והCLR מחפש התאמה בסדר של הפרמטרים והסוג שלהם מבלי לדרוש ששמות הפרמטרים יהיו זהים. &lt;/p&gt;
&lt;h1&gt;סיכום&lt;/h1&gt;
&lt;p&gt;בחלק זה ראינו כיצד מגדירים ומשתמשים בdelegate מבחינת syntax. &lt;/p&gt;
&lt;p&gt;בשבוע הבא אפרסם מאמר המשך עם דוגמאות שכיחות/פרקטיות לשימוש בdelegates.&lt;/p&gt;
&lt;p&gt;ערן.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=716136" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/Delegates/default.aspx">Delegates</category></item><item><title>Javascript – How to compare two object instances</title><link>http://blogs.microsoft.co.il/blogs/esakal/archive/2010/09/11/javascript-how-to-compare-two-object-instances.aspx</link><pubDate>Sat, 11 Sep 2010 21:07:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:697106</guid><dc:creator>Eran Sakal</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.microsoft.co.il/blogs/esakal/archive/2010/09/11/javascript-how-to-compare-two-object-instances.aspx#comments</comments><description>&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;מאמר זה מראה כיצד ניתן להשוות בין נתונים של 2 אובייקטים שונים ב-javascript.&lt;/div&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;&lt;strong&gt;&lt;u&gt;מוטיבציה&lt;/u&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;בשנה האחרונה היו 2 מצבים בהם נדרשתי ליכולת זו: 
&lt;ul&gt;
&lt;li&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;מצב 1 - פניתם לבסיס הנתונים וקיבלתם אובייקט המכיל נתונים על לקוח. לאחר זמן מסויים פניתם שוב לבסיס הנתונים ואתם מעוניינים לדעת אם הנתונים השתנו או לא. &lt;/div&gt;
&lt;li&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;מצב 2 - יש לכם מנגנון שמנהל היסטוריה של פעולות. כל פעולה מיוצגת באמצעות אובייקט המכיל אוסף של משתנים. כדי למנוע מאותה הפעולה להתבצע פעמים אתם רוצים להשוות בין הפעולה האחרונה שנעשתה לבין הפעולה שהמשתמש מנסה לעשות. &lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;במצבים שתוארו למעלה מדובר ב-2 אובייקטים שונים (מקומות שונים בזיכרון) ואנחנו מעוניינים לדעת אם הנתונים שלהם זהים או לא. אי-אפשר לבצע פעולת השוואה רגילה היות והשוואה רגילה בreference value משווה כתובות בזיכרון והתוצאה תמיד תהיה שהאובייקטים לא שווים. לכן דרוש פתרון חכם יותר שמשווה את המאפיינים של האובייקטים.&lt;/div&gt;&lt;/div&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;
&lt;h1&gt;פתרונות קוד&lt;/h1&gt;
&lt;h2&gt;פתרון 1&lt;/h2&gt;
&lt;p&gt;השתמשו בפונקציה הבאה להשוות בין האובייקטים. הפונקציה לא נכתבה על-ידי אך היות והשתמשתי בה לראשונה לפני שנה אין לי אפשרות למצוא את המקור ולתת לו קרדיט. &lt;/p&gt;&lt;/div&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;&lt;pre class="brush: js;"&gt;function compareObjects(x,y){ &lt;br /&gt;&lt;br /&gt;    x = (typeof x == &amp;#39;undefined&amp;#39;) ? null : x;&lt;br /&gt;    y = (typeof y == &amp;#39;undefined&amp;#39;) ? null : y;&lt;br /&gt;    &lt;br /&gt;    if (x == null || y == null)&lt;br /&gt;    {&lt;br /&gt;        return (x == null &amp;amp;&amp;amp; y == null)&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    for (var p in y) { &lt;br /&gt;        if(typeof(y[p]) !== typeof(x[p])) return false; &lt;br /&gt;        if((y[p]===null) !== (x[p]===null)) return false; &lt;br /&gt;        switch (typeof(y[p])) { &lt;br /&gt;            case &amp;#39;undefined&amp;#39;: &lt;br /&gt;                if (typeof(x[p]) != &amp;#39;undefined&amp;#39;) return false; &lt;br /&gt;                break; &lt;br /&gt;            case &amp;#39;object&amp;#39;: &lt;br /&gt;                if(y[p]!==null &amp;amp;&amp;amp; x[p]!==null &amp;amp;&amp;amp; (y[p].constructor.toString() !== x[p].constructor.toString() || !y[p].equals(x[p]))) return false; &lt;br /&gt;                break; &lt;br /&gt;            case &amp;#39;function&amp;#39;: &lt;br /&gt;                if (p != &amp;#39;equals&amp;#39; &amp;amp;&amp;amp; y[p].toString() != x[p].toString()) return false; &lt;br /&gt;                break; &lt;br /&gt;            default: &lt;br /&gt;                if (y[p] !== x[p]) return false; &lt;br /&gt;        } &lt;br /&gt;    } &lt;br /&gt;    return true; &lt;br /&gt;} &lt;/pre&gt;&lt;/div&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;
&lt;p&gt;&lt;strong&gt;דוגמאות שימוש&lt;/strong&gt;&lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;&lt;pre class="brush: js;"&gt;var instance1 = { name : &amp;#39;Eran&amp;#39;, aRank : [1,3,5] };&lt;br /&gt;var instance2 = { name : &amp;#39;Liron&amp;#39;, aRank : [1,3,5] };&lt;br /&gt;var instance3 = { name : &amp;#39;Liron&amp;#39;, aRank : [1,3,5] };&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;var isEqual = compareObjects(instance1,instance2); // result false (name is not the same)&lt;br /&gt;isEqual = compareObjects(instance2,instance3); // result true &lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;פתרון 2 (אלגנטי יותר אך לא בהכרח נחוץ)&lt;/h2&gt;&lt;/div&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;מפתחים רבים אוהבים פתרונות אלגנטים שבהם הפעולות נעשות ישירות על האובייקטים. ב-C# המציאו עבור זה יכולת בframework 3 שנקראת &lt;a href="http://geekswithblogs.net/BlackRabbitCoder/archive/2010/04/26/c-extension-methods---to-extend-or-not-to-extend.aspx" target="_blank"&gt;Extension Methods&lt;/a&gt;. יכולת זו קיימת בjs באמצעות הוספת הפונקציה לprototype.&lt;/div&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;בפתרון זה נוסיף פונקציה שנקראת “equals” לכל אובייקט. כפי שמעידה הכותרת, הפתרון אלגנטי ולרוב מורכב יותר מהנדרש. אבל טוב לדעת שהוא אפשרי.&lt;/div&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;&lt;strong&gt;איך עושים זאת?&lt;/strong&gt;&lt;/div&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;כל האובייקטים ב-javascript יורשים ממחלקה שנקראת Object. בנוסף, לכל מחלקה יש מאפיין שנקרא prototype. דרך prototype אפשר להגיע לכל המאפיינים של כל המחלקות מאותו הסוג (כולל אלו שיווצרו בעתיד). הוספת פונקציה ל – Object.prototype תתווסף לכל המאפיינים של כל האובייקטים (היות וכולם יורשים מ-Object).&lt;/div&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;נוסיף את הפונקציה הבאה מיד אחרי הפונקציה שמפתרון 1:&lt;/div&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;&lt;pre class="brush: js;"&gt;Object.prototype.equals = function(compareTo)&lt;br /&gt;{&lt;br /&gt;    return compareObjects(this,compareTo);&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;&lt;strong&gt;דוגמאות שימוש&lt;/strong&gt;&lt;/div&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;&lt;pre class="brush: js;"&gt;var instance1 = { name : &amp;#39;Eran&amp;#39;, aRank : [1,3,5] };&lt;br /&gt;var instance2 = { name : &amp;#39;Liron&amp;#39;, aRank : [1,3,5] };&lt;br /&gt;var instance3 = { name : &amp;#39;Liron&amp;#39;, aRank : [1,3,5] };&lt;br /&gt;&lt;br /&gt;var isEqual = instance1.equals(instance2); // result false (name is not the same)&lt;br /&gt;isEqual = instance2.equals(instance3); // result true &lt;/pre&gt;&lt;/div&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=697106" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/Web/default.aspx">Web</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/Javascript/default.aspx">Javascript</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/Tips/default.aspx">Tips</category></item><item><title>Site configuration manager - Easy to implement and use</title><link>http://blogs.microsoft.co.il/blogs/esakal/archive/2010/08/31/xmlconfiguration-infrastructure-easy-to-implement-amp-use.aspx</link><pubDate>Wed, 01 Sep 2010 00:00:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:687494</guid><dc:creator>Eran Sakal</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.microsoft.co.il/blogs/esakal/archive/2010/08/31/xmlconfiguration-infrastructure-easy-to-implement-amp-use.aspx#comments</comments><description>&lt;p style="text-align:right;direction:rtl;"&gt;כל אתר אינטרנט מכיל קונפיגורציות. השימוש בקובצי קונפיגורציות שכיח היות והוא מאפשר להשפיע על התנהגות האתר מבלי שצריך לקמפל את האתר כל פעם מחדש. לכן דאגו מתכנתי microsoft להוסיף מנגנון קונפיגורציה ב-asp.net וקראו לו בשם appsettings. עד כאן אני מניח שאני לא מחדש יותר מדי. &lt;/p&gt; &lt;p style="text-align:right;direction:rtl;"&gt;&lt;strong&gt;מאמר זה לא מדבר על appsettings&lt;/strong&gt; מכמה סיבות, כשהעיקרית ביניהן היא שמאוד קל ללמוד איך לעשות זאת ויש אלפי מאמרים שמראים איך. אז על מה המאמר בעצם?&amp;nbsp; מנסיוני, מתכנתים נזקקים לעיתים קרובות לניהול קונפיגורציה משוכלל יותר, אבל מסתפקים בappsettings פשוט כי הוא שם. בהמשך המאמר אני מסביר את ההבדלים בין התשתיות.&lt;/p&gt; &lt;p style="text-align:right;direction:rtl;"&gt;בכל מקום עבודה אליו הגעתי בשנים האחרונות, אחד הפיתוחים הראשונים שלי היה תשתית לניהול קונפיגורציות. הדרישה המרכזית: לבנות תשתית שתנהל את כל הלוגיסטיקה כגון טעינת הקובץ לזיכרון, ניטור הקובץ במידה והוא משתנה, שמירת נתונים מהאפליקציה חזרה לקובץ וניהול ThreadSafe. &lt;/p&gt; &lt;p style="text-align:right;direction:rtl;"&gt;&lt;strong&gt;&lt;u&gt;למי התשתית מיועדת&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p style="text-align:right;direction:rtl;"&gt;התשתית מיועדת לכל אתר שהוא לא מסוג &amp;quot;שגר ושכח&amp;quot; (אתרים קטנים שלאחר שמעלים אותם לאוויר הם לא משתנים לאורך זמן רב). התשתית עצמה פשוטה לשימוש למפתחים מכל הרמות.&lt;/p&gt; &lt;p style="text-align:right;direction:rtl;"&gt;&lt;strong&gt;&lt;u&gt;מאיפה מורידים את התשתית&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p style="text-align:right;direction:rtl;"&gt;הכנסו לקישור שמופיע בסוף המאמר. הורידו את התשתית והוסיפו אותה לאתר שלכם.&lt;/p&gt; &lt;h1 style="text-align:right;direction:rtl;"&gt;דרישות מרכזיות מתשתית קונפיגורציה&lt;/h1&gt; &lt;p style="text-align:right;direction:rtl;"&gt;סעיף זה מכיל רשימה של דרישות מרכזיות מתשתית לניהול קונפיגורציה. &lt;/p&gt; &lt;h2 style="text-align:right;direction:rtl;"&gt;דרישות פונקציונאליות&lt;/h2&gt; &lt;div style="text-align:right;direction:rtl;"&gt; &lt;ul&gt; &lt;li&gt;רכיב תשתיתי שיאפשר מיפוי של נתוני קונפיגורציה מקובץ לאובייקט בזיכרון.  &lt;li&gt;השליטה במבנה הנתונים של הקונפיגורציה צריכה להימצא בידי המתכנת אשר משתמש בתשתית.  &lt;li&gt;הרכיב צריך לשמור על סנכרון בין הקובץ לאובייקט בזיכרון. שינוי בקובץ צריך להשתקף במיידית באובייקט שבזיכרון - מבלי להשפיע על התנהלות האפליקציה.  &lt;li&gt;אפשרות לעריכת הנתונים בקובץ הקונפיגורציה ישירות מהאפליקציה באמצעות הרכיב התשתיתי.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt; &lt;h2 style="text-align:right;direction:rtl;"&gt;דרישות טכנולוגיות/תוכנה&lt;/h2&gt; &lt;div style="text-align:right;direction:rtl;"&gt; &lt;ul&gt; &lt;li&gt;הרכיב צריך לדעת לעבוד בסביבה מרובת משתמשים (Thread-safe) – למי שלא מכיר, סביבה שבה קוראים וכותבים בו זמנית לרכיב.  &lt;li&gt;יש לאפשר שיהיו מספר העתקים של הרכיב בו-זמנית באפליקציה כאשר כל העתק ינהל קובץ קונפיגורציה אחר. לדוגמא רכיב אחד ינהל קובץ משתמשים ורכיב אחר קובץ הגדרות אתר.  &lt;li&gt;הרכיב יכתוב נתונים טכנים ללוג על-מנת שאפשר יהיה לאתר תקלות בזמן מהיר. &lt;/li&gt;&lt;/ul&gt; &lt;h1&gt;רגע לפני - פתרונות קיימים ב-asp.net&lt;/h1&gt; &lt;h2&gt;הפתרון השכיח - שימוש ב-app settings&lt;/h2&gt;כאמור, הפתרון הפשוט והמוכר לניהול קונפיגורציות הוא appsettings. למי שלא מכיר, app settings ממוקם בקובץ web.config שם נשמרת הקונפיגורציה בצורה של אוסף אלמנטים כאשר כל אלמנט מורכב ממפתח (key) וערך (value) וזה נראה כך:  &lt;div style="text-align:left;direction:ltr;"&gt;&lt;pre class="brush: csharp;"&gt;&amp;lt;appSettings&amp;gt;&lt;br /&gt;    &amp;lt;add key=&amp;quot;Global.MaintainanceMode&amp;quot; value=&amp;quot;true&amp;quot;/&amp;gt;&lt;br /&gt;    &amp;lt;add key=&amp;quot;Site.Title&amp;quot; value=&amp;quot;Eran Sakal - Blog&amp;quot;/&amp;gt;    &lt;br /&gt; &amp;lt;/appSettings&amp;gt;
&lt;/pre&gt;&lt;/div&gt;&lt;u&gt;לעבודה עם appsettings יש מספר חסרונות: &lt;/u&gt;
&lt;ul&gt;
&lt;li&gt;שינוי של ה-appsettings משפיע על כלל האפליקציה (מבצע ריסטרט לאפליקציה). אחת ההשלכות של זה הינו איבוד הsessions של המשתמשים המחוברים באותו הרגע. 
&lt;li&gt;מבנה הנתונים של הappsettings קבוע (אוסף מפתחות וערכים) ולא משקף בהכרח את המבנה הנדרש עבור הרכיב המדובר. לדוגמא, אין אפשרות ליצור היררכיה של נתונים. 
&lt;li&gt;היות וה-appsettings משותף לכלל האפליקציה. נוצר ערבוב בין הקונפיגורציות של המודולים השונים. מצב זה יכול להוביל להתנגשות בין קונפיגורציות וקושי לשייך קונפיגורציה למודול הרלוונטי. 
&lt;li&gt;לא ניתן לבצע עדכון של קונפיגורציה מהזיכרון לקובץ - web.config (אני כותב סעיף זה עם הסתייגות קלה היות וישנה דרך אך היא לא מומלצת ולא טובה).&lt;/li&gt;&lt;/ul&gt;
&lt;p style="text-align:right;direction:rtl;"&gt;&lt;u&gt;כמובן שישנם מצבים שבהם נוח ונכון להשתמש בapp settings:&lt;/u&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;כשרוצים להגדיר הגדרות של האפליקציה עצמה. דוגמאות: 
&lt;ul&gt;
&lt;li&gt;אם יש טופס צור קשר – רשימת המיילים אליהם יישלחו הפניות מהטופס. 
&lt;li&gt;אם יש קבצים בשימוש האפליקציה – כתיבת הנתיב המלא לקובץ. 
&lt;li&gt;אם יש פרסומות באתר ורוצים שתהיה אפשרות להעלים אותם או להציג אותם בצורה מהירה.&lt;/li&gt;&lt;/ul&gt;
&lt;li&gt;פיתוח מהיר - קל ואינטואיטיבי להשתמש בappsettings.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;מאמר זה לא מתמקד בעבודה עם appsettings ולכן לא ארחיב על השימוש. ניתן לקרוא את &lt;a href="http://www.devasp.net/net/articles/display/679.html" target="_blank"&gt;המאמר החיצוני הבא&lt;/a&gt; המכיל דוגמאות קוד לנושא.&lt;/p&gt;
&lt;h2&gt;פתרון מתקדם יותר - שימוש ב-config section&lt;/h2&gt;
&lt;p&gt;אפשרות זו פחות מוכרת ולכן גם פחות בשימוש. למי שלא מכיר, ניתן להגדיר מקטע XML בקובץ web.config ויש לכם שליטה מלאה על המבנה שלו. מדובר בתשתית שמאפשרת לכם לגשת בקלות אל הנתונים מהאפליקציה. אפשרות זו פותרת 2 חסרונות גדולים בעבודה עם app settings והם:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;המתכנת יכול להגדיר את מבנה הXML בהתאם לצורכי המודול. 
&lt;li&gt;ניתן להגדיר מקטעים נפרדים עבור כל מודול ובכך למנוע ערבוב של הקונפיגורציות. הקוד הבא מראה דוגמא לconfig section:&lt;/li&gt;&lt;/ol&gt;
&lt;div style="text-align:left;direction:ltr;"&gt;&lt;pre class="brush: csharp;"&gt;&amp;lt;SiteConfiguration&amp;gt;&lt;br /&gt;  &amp;lt;Global MaintainanceMode=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/Global&amp;gt;&lt;br /&gt;  &amp;lt;Information&amp;gt;&lt;br /&gt;    &amp;lt;Title&amp;gt;Eran Sakal - Blog&amp;lt;/Title&amp;gt;&lt;br /&gt;  &amp;lt;/Information&amp;gt;&lt;br /&gt;&amp;lt;/SiteConfiguration&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;פתרון זה אומנם נותן מענה לדרישות נוספות מהרשימה אך לא לכולם. מאמר זה לא מתמקד בעבודה עם config section. ניתן לקרוא את &lt;a href="http://www.4guysfromrolla.com/articles/020707-1.aspx" target="_blank"&gt;המאמר החיצוני הבא&lt;/a&gt; המכיל דוגמאות קוד לנושא.&lt;/p&gt;
&lt;h1&gt;תשתית חכמה לניהול קונפיגורציות &lt;/h1&gt;
&lt;p&gt;התשתית במאמר זה, &amp;quot;XmlConfiguration Manager&amp;quot;, עונה על כלל הדרישות שמוגדרות למעלה. למעשה, היא נכתבה על-בסיס הדרישות הנ&amp;quot;ל. הטבלה הבאה רשימה פונקציונלית של הדרישות:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Configuration Scope&lt;/strong&gt; – אפשרות להגדיר קונפיגורציה לכל מודול בנפרד. 
&lt;li&gt;&lt;strong&gt;Behavior on changes in configuration file&lt;/strong&gt; – סנכרון הנתונים עבור המודול הרלוונטי מבלי להפריע להתנהלות האפליקציה. 
&lt;li&gt;&lt;strong&gt;Configuration data structure&lt;/strong&gt; – גמישות בהגדרת מבנה הנתונים של הקונפיגורציה עבור כל מודול. 
&lt;li&gt;&lt;strong&gt;Multiple configuration handling&lt;/strong&gt; – שימוש במספר קונפיגורציות באפליקציה בו-זמנית למספר מודולים מבלי שתהיה התנגשות ביניהם. 
&lt;li&gt;&lt;strong&gt;Behavior on configuration error&lt;/strong&gt; – בידוד התקלה במקרה של קונפיגורציה שגויה כך שרק פעולות הקשורות ישירות לקונפיגורציה הבעייתית יושפעו. 
&lt;li&gt;&lt;strong&gt;Updating configuration file from application&amp;nbsp; &lt;/strong&gt;- תמיכה בביצוע עדכון הפוך של קובץ הקונפיגורציה מתוך האפליקציה. 
&lt;li&gt;&lt;strong&gt;Multi-threaded environment&lt;/strong&gt; – עבודה בסביבה מרובת משתמשים (כגון אתרי אינטרנט). 
&lt;li&gt;&lt;strong&gt;Technical Logging&lt;/strong&gt; – אינטגרציה עם תשתית logging באמצעותה אפשר לנטר את המתרחש בתשתית.&amp;nbsp;&amp;nbsp; &lt;li&gt;&lt;strong&gt;Ease of use &lt;/strong&gt;- שימוש בפרוטוקלים מוכרים על-מנת למזער את זמן הלמידה והשימוש בתשתית.&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;ניתן לצפות בטבלת השוואה בין מימוש הדרישות בתשתית זו לבין המימוש בכלים appsettings/config section. &lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/comparison_7AF78B1F.jpg" target="_blank"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="Comparison Table" border="0" alt="Comparison Table" src="http://blogs.microsoft.co.il/blogs/esakal/comparison_thumb_463973FB.jpg" width="244" height="172" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;* לחצו על התמונה להגדלה&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;דרישות קדם לשימוש בתשתית &lt;/h2&gt;
&lt;p&gt;על-מנת לעבוד בתשתית צריך להכיר שימוש בXPath. התשתית משתמשת בפרטוקול XML לשמירת נתונים בקובץ הקונפיגורציה כאשר הכי קל להשתמש בXPath כדי להמיר את הנתונים ממבנה XML לאובייקט ב-CSharp וחזרה. מי שמכיר את העבודה עם XPath ורק צריך רענון מוזמן לגלוש &lt;a href="http://www.codeproject.com/KB/cpp/myXPath.aspx" target="_blank"&gt;לקישור הבא&lt;/a&gt;. אם אינכם מכירים את הנושא תגלשו &lt;a href="http://www.w3schools.com/xpath/" target="_blank"&gt;לקישור הבא&lt;/a&gt; המכיל מדריך מפורט וברור. &lt;/p&gt;
&lt;h1&gt;עיקרי תשתית – XML Configuration Manager&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;כל שינוי שמבוצע בקובץ הקונפיגורציה מנוטר אוטומטית והתשתית מעדכנת את האובייקט בזיכרון. 
&lt;li&gt;התשתית מבצעת כתיבה של נתונים טכנים ללוג באמצעות &lt;a href="http://logging.apache.org/log4net/index.html" target="_blank"&gt;Log4net&lt;/a&gt;. 
&lt;li&gt;התשתית מפותחת על-בסיס עקרונות של הנושאים&amp;nbsp; Thread Safety ו-ExceptionHandling. 
&lt;li&gt;הקוד מכיל תיעוד מלא.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;התשתית מורכבת ממחלקה מרכזית בשם XmlConfigurationManager.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/XmlConfigurationManager_12D4D6A2.jpg" target="_blank"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="XmlConfigurationManager" border="0" alt="XmlConfigurationManager" src="http://blogs.microsoft.co.il/blogs/esakal/XmlConfigurationManager_thumb_191E3DE1.jpg" width="220" height="244" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;* לחצו על התמונה להגדלה&lt;/p&gt;
&lt;h2&gt;כיצד מטמיעים את התשתית&lt;/h2&gt;
&lt;p&gt;הרשימה הבאה מראה את הצעדים הנדרשים להטמעת התשתית בפרויקט.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;הוסיפו את התשתית לאתר (בצעו reference או מקמו בספריית bin). 
&lt;li&gt;צרו קובץ XML שמכיל את הנתונים שלכם (&lt;strong&gt;להלן – קובץ הקונפיגורציה&lt;/strong&gt;) 
&lt;li&gt;הגדירו מחלקה שמייצגת את מבנה הנתונים הנדרש (&lt;strong&gt;להלן – מחלקת הנתונים&lt;/strong&gt;). 
&lt;li&gt;הגדירו מחלקה שתנהל את סנכרון הנתונים (&lt;strong&gt;להלן – מחלקת הניהול&lt;/strong&gt;). בצעו ירושה למחלקה XmlConfigurationManager והעבירו כgeneric parameter את מחלקת הנתונים. 
&lt;li&gt;ממשו את המתודה האבסטרקטית &lt;strong&gt;SyncInstanceForRead.&lt;/strong&gt;&amp;nbsp; מתודה זו אחראית לייצר אובייקט נתונים מקובץ הקונפיגורציה. 
&lt;li&gt;בצעו איתחול לאובייקט באחת מ-2 הדרכים הבאות:&lt;/li&gt;&lt;/ol&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;שימוש ב-&lt;strong&gt;Constructor – &lt;/strong&gt;הצורה הסטנדרטית. ניתן להעביר את הנתיב של הקובץ באיתחול האובייקט. במצב כזה קובץ הנתונים ייקרא מיידית. 
&lt;li&gt;קריאה למתודה &lt;strong&gt;Initialize&lt;/strong&gt; – שיטה זו מומלצת אם מעוניינים להרשם קודם לאחד מהאירועים (פירוט על האירועים בהמשך הסעיף).&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;
&lt;h2&gt;כיצד משתמשים בתשתית&lt;/h2&gt;
&lt;p&gt;הרשימה הבאה מכילה מתודות ואירועים שדרכם ניגשים לקונפיגורציה.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;המתודות הבאות משמשות לעבודה מול מחלקת הניהול: 
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TryGetData&lt;/strong&gt; – מתודה זו מאפשרת קבלה של אובייקט הנתונים. המתודה מוודאת קודם שהנתונים עדכניים. שימוש בשיטה &lt;strong&gt;TryGetData&lt;/strong&gt; מכווין לטיפול נכון במצבים שבהם הנתונים לא זמינים. 
&lt;li&gt;&lt;strong&gt;IsValid&lt;/strong&gt; – מתודה זו משמשת במצבים בהם רוצים לדעת אם הנתונים זמינים אבל לא צריכים להשתמש בנתונים אלו. 
&lt;li&gt;&lt;strong&gt;SaveConfiguration&lt;/strong&gt; – מתודה זו מאפשרת שמירה של שינויים שנעשו באובייקט הנתונים ישירות לקובץ הקונפיגורציה. כדי להשתמש במתודה זו צריך לממש את הממשק &lt;strong&gt;&amp;#39;ISupportSave&amp;#39;&lt;/strong&gt;.&lt;/li&gt;&lt;/ul&gt;
&lt;li&gt;האירועים הבאים מאפשרים התערבות בתהליך עדכון הנתונים מהקובץ לזיכרון 
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;DataChanging&lt;/strong&gt; – אירוע זה מאפשר להציץ על אובייקט הנתונים החדש לפני שהוא מתעדכן בזיכרון ובמידת הצורך לכפות ביטול של פעולת העדכון. 
&lt;li&gt;&lt;strong&gt;DataChanged&lt;/strong&gt; – אירוע זה נקרא לאחר סנכרון ונועד למצבים מתקדמים כגון עדכון אובייקט אחר שתלוי בנתוני הקונפיגורציה שהשתנו.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;h2&gt;דוגמא לקובץ קונפיגורציה&lt;/h2&gt;
&lt;p&gt;בקישור הבא צירפתי קונפיגורציה לדוגמא שמנוהלת באמצעות התשתית. מדובר בקונפיגורציה שלקוחה מאתר מוכר ואחראית על איזורי הפרסומות באתר. הקונפיגורציה אולי תיראה לכם פשוטה אבל זו בדיוק המטרה – לבנות קונפיגורציה במבנה XML שמותאם לצרכי האתר בקלות.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/posts/2508-configuration/adv.txt" target="_blank"&gt;לחצו כאן לצפיה בדוגמא של קובץ קונפיגורציה&lt;/a&gt; &lt;/p&gt;
&lt;h2&gt;הורדת התשתית&lt;/h2&gt;
&lt;p&gt;במאמר זה הראתי תשתית שבאמצעותה תוכלו לנהל בקלות ובגמישות קונפיגורציות באתרכם. בקישור הבא ניתן להוריד את הרכיב כולל קוד מקור ודוגמאות שימוש. מקווה שתמצאו את התשתית מועילה עבורכם. תרגישו חופשי לשאול שאלות.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://projects.eransakal.com/configuration/default.aspx" target="_blank"&gt;&lt;strong&gt;לחצו כאן להורדת התשתית&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;במידה והקישור למעלה לא עובד – הורידו באופן ישיר מהקישורים הבאים:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://blogs.microsoft.co.il/files/folders/697846/download.aspx" target="_blank"&gt;&lt;strong&gt;קוד מקור כולל פרוייקט לדוגמא&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blogs.microsoft.co.il/files/folders/697837/download.aspx" target="_blank"&gt;&lt;strong&gt;קבצים בינארים להטמעה מיידית&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;ערן.&lt;/p&gt;&lt;/div&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=687494" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/Configuration/default.aspx">Configuration</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/Infrastructure/default.aspx">Infrastructure</category></item><item><title>How to avoid spaghetti code in javascript</title><link>http://blogs.microsoft.co.il/blogs/esakal/archive/2010/08/25/why-knowing-singleton-syntax-in-javascript-is-important.aspx</link><pubDate>Thu, 26 Aug 2010 01:54:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:692249</guid><dc:creator>Eran Sakal</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.microsoft.co.il/blogs/esakal/archive/2010/08/25/why-knowing-singleton-syntax-in-javascript-is-important.aspx#comments</comments><description>&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;
&lt;p&gt;javascript מאוד פופולרית באתרי web. כל הדפדפנים השכיחים תומכים בjavascript. כמעט כל אתר משתמש בjavascript לבצע פעולות UI בדפדפן. אז מדוע מעטים האנשים שחושבים שהיא שפה נחמדה לתכנות?&lt;/p&gt;
&lt;p&gt;בתור התחלה קשה לדעת איזה סוג שפה היא.&amp;nbsp; מרבית האנשים יגידו שהיא שפה פונקציונלית. אבל אפשר להגדיר בה אובייקטים, &lt;a href="http://stackoverflow.com/questions/107464/is-javascript-object-oriented" target="_blank"&gt;האם זה אומר ש-JS היא אולי שפה מכוונת&amp;nbsp; עצמים (OOP)&lt;/a&gt;? אבל אין בה ירושה – אז איך היא תהיה OOP? בגלל שJS היא שפה מאוד כללית עם מעט מאוד מגבלות, ובגלל שקשה לקטלג אותה לפרדיגמת תכנות כלשהי, נוצר חוסר בהירות לגבי השימוש בה. התוצאה המתקבלת לרוב היא &lt;a href="http://he.wikipedia.org/wiki/%D7%A7%D7%95%D7%93_%D7%A1%D7%A4%D7%92%D7%98%D7%99" target="_blank"&gt;קוד ספגטי&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;מאמר זה הינו הראשון מתוך סדרת מאמרים בנושא &lt;strong&gt;כתיבה פרקטית בשפת javascript באתרי web&lt;/strong&gt;. בחרתי להראות במאמר זה כיצד מגדירים אובייקטים בJS ובכך להמנע מקבצים ארוכים המכילים כמויות של פונקציות גלובליות - ליכולת זו יתרונות רבים:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;קריאות קוד – חלוקה לאובייקטים יוצרת הפרדה בין הפונקציות לפי מודולים. 
&lt;li&gt;מפשט את התחזוקה של הקוד. 
&lt;li&gt;מאפשר לבצע בקלות code reuse. 
&lt;li&gt;תמיכה בכימוס (Encapsulation) – מאמר זה לא מרחיב על יתרון זה אך הוא מהווה הקדמה לנושא. במאמר נפרד אראה כיצד ניתן להגדיר משתנים/פונקציות מסוג private. יכולת זו תאפשר יצירה של אובייקטים אוטונמים. &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;בסעיף הבא אני מסביר בקצרה מהי שפה דינמית ומה הכוח הטמון בשפה JS. מי שרוצה לעבור למימוש מוזמן לדלג על ההקדמה ולעבור ישירות לסעיף שאחרי. &lt;/p&gt;
&lt;h1&gt;רגע לפני – javascript = שפה דינמית?&lt;/h1&gt;
&lt;p&gt;השפה javascript היא שפה דינמית. שפה דינמית היא שפה עילית שמבצעת בזמן ריצה פעולות שמבוצעות בדרך-כלל בזמן ההידור (compliation) כגון הגדרת משתנים, יצירת פונקציות חדשות, הרחבת אובייקטים קיימים. כל הפעולות הנ&amp;quot;ל מתבצעות בזמן ריצה. 
&lt;p&gt;למה חשוב לדעת שjavascript היא שפה דינמית? מי שלא עבד עם שפה דינמית ולא מכיר את היתרונות בשפה דינמית נוטה לחשוב שjs היא שפה חלשה , כתובה לא נכון, מעודדת שגיאות ובעיות שקשה לדבג. אחרי שלומדים לנצל את יתרונות השפה הדינמית מגלים שהיא מאפשרת כלים פשוטים אך עם זאת עוצמתיים – צריך רק לאזור אומץ ולהיות סבלניים ופתוחים לנושא.&amp;nbsp; 
&lt;p&gt;אומנם היום אני חכם גדול, אבל עד לפני מספר חודשים אפשר להגיד שהייתי סקריפטופוב רציני. אני מתכנת 4 שנים בweb וכתבתי לא מעט ב-JS אבל תמיד ניסיתי למזער את השימוש עד כמה שאפשר. לפני זמן מה קיבלתי עבודה ש&amp;quot;אילצה&amp;quot; אותי לפתח מערכת בjs עם ארכיטקטורה מורכבת ודרישות למודולריות, טיפול נכון בשגיאות (מישהו אמר logging ב-javascript?), ניהול אירועים, עמידה בעומסים ועוד הרבה מטעמים נוספים. בהתחלה נבהלתי כל-כך שסירבתי לקבל את העבודה. אך בסוף התרצתי ותוך כדי עבודה גיליתי שיש לא מעט כלים שהרוב לא מכירים והם יכולים להיות מאוד יעילים בתכנות בJS. ואלו הנושאים שארחיב עליהם במאמרים הבאים: 
&lt;ul&gt;
&lt;li&gt;שימוש נכון באובייקטים בקבצי JS (&lt;strong&gt;מאמר זה)&lt;/strong&gt; 
&lt;li&gt;מספר דרכים ליצירת &amp;quot;מחלקות&amp;quot; 
&lt;li&gt;הגדרת scoping באפליקציה (ובפרט private members). 
&lt;li&gt;שימוש ב-Regular Expression. 
&lt;li&gt;טיפול נכון ומניעה מקדימה של&amp;nbsp; שגיאות. 
&lt;li&gt;עבודה עם namespaces. 
&lt;li&gt;יצירת מנגנון באירועים (events). 
&lt;li&gt;יכולות מתקדמות בשפה דינמית.&lt;/li&gt;&lt;/ul&gt;
&lt;h1&gt;חזרה לנושא – כיצד מייצרים אובייקט&lt;/h1&gt;
&lt;p&gt;האם אתם מתכנתי web? אם כן אז כנראה כתבתם בשפת js. אני מניח שיש לכם בממוצע 10-40 פונקציות בכל אתר. ומשתנים (var) גלובלים – בטח גם כאלה יש בקוד? אם התשובה היא כן אז יש לי שאלה אליכם – האם כל הפונקציות מוגדרות בעמוד או בקובץ נפרד? האם הקפדתם לקבץ משתנים ופונקציות ליחידות עצמאיות (אובייקטים)? תסתכלו על הקובץ הבא (לקוח מאתר מוכר בארץ) – קובץ זה ממחיש כתיבה שכיחה (ומבלוגנת) של קוד js באתרים. 
&lt;p&gt;&lt;strong&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/posts/2408-js1/js-example-mess.txt" target="_blank"&gt;קובץ לדוגמא עם קוד JS מבולגן&lt;/a&gt;&lt;/strong&gt; 
&lt;p&gt;בסוף המאמר הוספתי קובץ שמראה קוד לדוגמא מחולק לאובייקטים. 
&lt;h2&gt;קיבוץ פונקציות ומשתנים לאובייקטים&lt;/h2&gt;
&lt;p&gt;הגדרת האובייקט מבוססת על פורמט שנקרא JSON, או בשמו המלא Javascript Object Notation. 
&lt;p&gt;&lt;u&gt;הגדרה פשוטה&lt;/u&gt; 
&lt;p&gt;הדוגמא הבאה מראה הגדרה של אובייקט עם מספר מאפיינים: 
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;&lt;pre class="brush: js;"&gt;var oUser = { sName : &amp;#39;eran&amp;#39;, nAge : 30, bMarried : true };&lt;br /&gt;// alternative syntax (the same meaning as the above)&lt;br /&gt;var oUser = { &amp;#39;sName&amp;#39; : &amp;#39;eran&amp;#39;, &amp;#39;nAge&amp;#39; : 30, &amp;#39;bMarried&amp;#39; : true };
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;כאשר: 
&lt;ul&gt;
&lt;li&gt;בJSON האובייקט עטוף בסוגריים מסולסלים. 
&lt;li&gt;כל מאפיין מורכב משם מאפיין וערך כאשר הם מופרדים באמצעות הסימן נקודותיים. 
&lt;li&gt;כל זוג מאפיינים מופרד באמצעות הסימן פסיק. 
&lt;li&gt;את שם המאפיין ניתן להגדיר בלי/עם מרכאות – המשמעות זהה. 
&lt;li&gt;סוג המאפיין נגזר מהערך שהושם לתוכו (לדוגמא bMarried הוא ערך בוליאני ו-nName הוא מחרוזת). 
&lt;li&gt;כתיבת אובייקט בפורמט json מגדירה את מבנה האובייקט ובsyntax הנ&amp;quot;ל האובייקט מאותחל אוטומטית לתוך המשתנה (בדוגמא למעלה לתוך oUser). לא ניתן ליצור אובייקטים נוספים באמצעות שימוש במילה השמורה new.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;דוגמא לעבודה עם האובייקט: 
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;&lt;pre class="brush: js;"&gt;// change user name&lt;br /&gt;oUser.sName = &amp;quot;liron&amp;quot;;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;u&gt;הגדרת מערך של אובייקטים&lt;/u&gt; 
&lt;p&gt;בדוגמא זו נראה כיצד מגדירים אובייקט שהוא מערך של אובייקטים: 
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;&lt;pre class="brush: js; toolbar: false;"&gt;var arrColors = [ &amp;#39;red&amp;#39;, &amp;#39;green&amp;#39;, &amp;#39;yellow&amp;#39; ];&lt;br /&gt;var arrCar = [ {sManufacturer : &amp;#39;toyota&amp;#39;, sModel : &amp;#39;corolla&amp;#39;}, { sManufacturer : &amp;#39;subaro&amp;#39;, sModel :&amp;#39;impreza&amp;#39;}];&lt;br /&gt;&lt;br /&gt;.
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;כאשר: 
&lt;ul&gt;
&lt;li&gt;בJSON המערך עטוף בסוגריים מרובעים. 
&lt;li&gt;כל אלמנט במערך מייצג אובייקט. 
&lt;li&gt;שורה 1 - ניתן להגדיר אלמנטים מסוגים פשוטים (מחרוזות, ערכים בוליאנים, ערכים מספרים) 
&lt;li&gt;שורה 2 - ניתן להגדיר אלמנטים שהם בעצמם אובייקטים. &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;דוגמא לעבודה עם אחד המערכים: 
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;&lt;pre class="brush: js;"&gt;if (arrCar[0].sManufacturer == &amp;#39;toyota&amp;#39;)&lt;br /&gt;{&lt;br /&gt;    // do something&lt;br /&gt;}
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;u&gt;הגדרה מורכבת &lt;/u&gt;
&lt;p&gt;דוגמא זו מראה כיצד ניתן להגדיר אובייקט בתוך אובייקט, מאפיינים מסוג פונקציות ושימוש במערך בתוך אובייקט: 
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;&lt;pre class="brush: js;"&gt;var oUser = {&lt;br /&gt;    sName : &amp;#39;eran&amp;#39;, &lt;br /&gt;    arrChildren : [],&lt;br /&gt;    oStatus : {bIsHappy : true, bIsFriendly : true},  &lt;br /&gt;    introduce : function() &lt;br /&gt;    {&lt;br /&gt;        alert(this.sName);&lt;br /&gt;    }&lt;br /&gt;};
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;כאשר:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;כתבתי כל מאפיין בשורה נפרדת. זה נעשה לצורך קריאות בלבד. אפשר לכתוב את הכל בשורה אחת. 
&lt;li&gt;המאפיין arrChildren הוא מסוג מערך וכרגע אין לו ערכים. 
&lt;li&gt;המאפיין oStatus הוא אובייקט פנימי (מאותחל אוטומטית כפי שראינו בהגדרה הפשוטה). 
&lt;li&gt;המאפיין Introduce הוא מסוג פונקציה. &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;דוגמא לשימוש באובייקט:&lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;&lt;pre class="brush: js;"&gt;// add child to array&lt;br /&gt;oUser.arrChildren.push({sName : &amp;#39;gali&amp;#39;});&lt;br /&gt;&lt;br /&gt;// access inner object&lt;br /&gt;oUser.oStatus.bIsHappy = true;&lt;br /&gt;&lt;br /&gt;// execute object function&lt;br /&gt;oUser.introduce();
&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;הגדרת אובייקט ברמת האפליקציה&lt;/h2&gt;
&lt;p&gt;יש 2 דרכים להגדיר את האובייקט ברמת האפליקציה. 
&lt;p&gt;&lt;u&gt;דרך 1 – הגדרה עקיפה (implicit)&lt;/u&gt; 
&lt;p&gt;כדי ליצור אובייקט ברמת האפליקציה נגדיר&amp;nbsp; משתנה במקום כלשהו בעמוד. יש לוודא שהוא לא מוגדר בתוך פונקציה. במאמר נפרד אתמקד בנושא הscoping של משתנים. בשלב זה מספיק להבין שאם הגדרתם משתנה כלשהו ברמת העמוד, הוא יהיה נגיש בכל מקום בקוד. 
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;&lt;pre class="brush: js;"&gt;var oUser = { sName : &amp;#39;eran&amp;#39;, nAge : 30, bMarried : true };
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;u&gt;דרך 2 – הגדרה ישירה (explicit)&lt;/u&gt; 
&lt;p&gt;בדרך זו נעבוד עם האובייקט window ונוסיף אליו את האובייקט שיצרנו. 
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;&lt;pre class="brush: js;"&gt;window[&amp;quot;oUser&amp;quot;] = { sName : &amp;#39;eran&amp;#39;, nAge : 30, bMarried : true };
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;חשוב לציין ששתי הדרכים מבצעות את אותו הדבר. ההבדל היחידי הוא שבדרך 1 כשמגדירים משתנה ברמת העמוד הוא אוטומטית מתווסף לאובייקט window. בדרך 2 אנחנו מוסיפים אותו בעצמנו לאובייקט window. 
&lt;h2&gt;סיכום&lt;/h2&gt;
&lt;p&gt;במאמר זה ראינו דרך נוחה להגדרת אובייקט בשפה javascript. לשיטה זו יתרונות רבים. אני ממליץ בחום לנסות את השיטה רק תזהרו – זה ממכר. בקישור הבא ניתן לראות דוגמא לקוד שנלקח מאתר מוכר ונכתב כמתואר במאמר זה:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/posts/2408-js1/js-example-good.txt" target="_blank"&gt;קובץ לדוגמא עם קוד JS מחולק נכון (שימוש בכלים שכתובים במאמר זה)&lt;/a&gt;&lt;/strong&gt;&amp;nbsp; &lt;/p&gt;
&lt;h3&gt;הערות לסיום&lt;/h3&gt;
&lt;p&gt;&lt;u&gt;האם יש הבדל בין קוד שנכתב בקובץ js חיצוני לקוד שנכתב בתוך העמוד?&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;מבחינה פונקציונאלית אין הבדל. הדפדפן מייבא את קובץ הjs החיצוני ו&amp;quot;מדביק&amp;quot; את התוכן שלו בתוך העמוד. מכאן שניתן להגדיר אובייקטים בקובץ חיצוני או בתוך העמוד ושניהם יתנהגו באופן זהה. קיים הבדל הקשור לביצועים אבל זה לא רלוונטי למאמר זה.&lt;/p&gt;
&lt;p&gt;&lt;u&gt;כיצד לקרוא לפונקציה A מתוך פונקציה B כששתי הפונקציות שייכות לאובייקט&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;נשתמש במילה השמורה this. אופציה נוספת - היות ומדובר באובייקט שנוצר ברמת האפליקציה ניתן לפנות אליו על-ידי שימוש בשם המלא של האובייקט. הקוד הבא מראה דוגמא לשימוש בשתי האפשרויות:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;&lt;pre class="brush: js;"&gt;var oSearch = {&lt;br /&gt;    performSearch : function(sQuery)&lt;br /&gt;    {&lt;br /&gt;        // alternative 1 - using the reserved word &amp;#39;this&amp;#39;&lt;br /&gt;        this.executeSearch(sQuery,false);&lt;br /&gt;        // alternative 2 - calling the application object &amp;#39;oSearch&amp;#39; (defined in line 1)&lt;br /&gt;        oSearch.executeSearch(sQuery,false);&lt;br /&gt;    },&lt;br /&gt;    executeSearch : function(sQuery, bIsAjax)&lt;br /&gt;    {&lt;br /&gt;        // handle the execute request&lt;br /&gt;    }    &lt;br /&gt;}     
&lt;/pre&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;
&lt;p&gt;חשוב לדעת – אם תבצעו קריאה לפונקציה באופן ישיר תקבלו שגיאה – יש להשתמש באחת משתי הדרכים הרשומות למעלה.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;ערן.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=692249" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/Web/default.aspx">Web</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/Javascript/default.aspx">Javascript</category></item><item><title>Sending an sms from C# in 3 steps</title><link>http://blogs.microsoft.co.il/blogs/esakal/archive/2010/07/22/sending-an-sms-from-c-in-3-steps.aspx</link><pubDate>Thu, 22 Jul 2010 18:27:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:682219</guid><dc:creator>Eran Sakal</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.microsoft.co.il/blogs/esakal/archive/2010/07/22/sending-an-sms-from-c-in-3-steps.aspx#comments</comments><description>&lt;div dir="rtl" align="right"&gt;
&lt;h1&gt;שליחת הודעות SMS מאפליקציה ב-3 שלבים פשוטים&lt;/h1&gt;
&lt;p dir="rtl" align="right"&gt;חיי המתכנת קלים מאוד בתקופתנו בהשוואה לחצי עשור אחורה. היום אפשר לבנות אפליקציות שלמות המבוססות על אינטגרציות למערכות ייעודיות, מקצועיות ובוגרות בתחומן. אחד האפליקציות שפיתחתי דרשה יכולת שליחה של הודעות SMS ללקוחות. &lt;/p&gt;
&lt;p dir="rtl" align="right"&gt;ההודעות מיועדות להשלח בארצנו בלבד ולכן חיפשתי פתרונות מקומיים העונים על הדרישות הבסיסיות הבאות: &lt;/p&gt;
&lt;div dir="rtl" align="right"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div align="right"&gt;התממשקות למערכת שליחת הודעות SMS באמצעות webservice.&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div align="right"&gt;אפשרות לשליחת הודעה למספר נמענים בו-זמנית וקבלת חיווי על הצלחה/כשלון.&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div align="right"&gt;ממשק ניהול נוח ליצירת דוחות מעקב.&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div align="right"&gt;זמינות של תמיכה ושירות.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;
&lt;p align="right"&gt;מגיגול שעשיתי איתרתי 3 חברות רלוונטיות:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;div align="right"&gt;&lt;a href="http://www.simplesms.co.il/" target="_blank"&gt;Simple SMS&lt;/a&gt;&amp;nbsp;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div align="right"&gt;&lt;a href="http://www.smartsms.co.il/SmartSMS-API.sms" target="_blank"&gt;Smart SMS&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div align="right"&gt;&lt;a href="http://www.inforu.co.il/" target="_blank"&gt;שמיר מערכות – inforU&lt;/a&gt;&amp;nbsp;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;p align="right"&gt;&lt;strong&gt;בחרתי לנסות את “Simple Sms” &lt;/strong&gt;היות והאתר שלהם מכיל את מלוא האינפורמציה הנדרשת. מדפדוף באתר אפשר לדעת עלויות, פרטים על דרך ההתממשקות, טפסים אלקטרונים לרכישת חבילת הודעות. אז רכשתי חבילת הודעות, הורדתי קוד לדוגמא, הקלדתי את הפרטים הרלוונטים ו… השליחה נכשלה בתואנה שאין לי חבילת הודעות. לימים גיליתי כי הצד החלש שלהם הוא השירות. כשמתקשרים ב-90% מהפעמים מגיעים למוקדנים חיצוניים לחברה וכל מה שאפשר זה להשאיר הודעה ולהמתין.&amp;nbsp; אך היות וכבר רכשתי חבילת הודעות החלטתי לתת להם צ’אנס ולהמשיך בהתממשקות. תמיד אפשר להחליף בקלות בהמשך אם רוצים.&lt;/p&gt;
&lt;p align="right"&gt;לפני שנמשיך&amp;nbsp; רציתי לציין כי “שמיר מערכות” עשו עלי את הרושם הרציני ביותר עם סל המוצרים עשיר מבין שלושת החברות. ייתכן ובזמן הקרוב אדרש לממשק אפליקציה לשירותי SMS. במידה וזה יקרה אעדכן בפוסט את חווית העבודה מולם.&lt;/p&gt;
&lt;p align="right"&gt;&lt;strong&gt;במאמר זה נראה איך ב-3 שלבים פשוטים ניתן להוסיף יכולות שליחה של הודעות SMS מאפליקציות .net.&lt;/strong&gt;&lt;/p&gt;
&lt;p align="right"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p align="right"&gt;&amp;nbsp;&lt;img style="BORDER-RIGHT-WIDTH:0px;DISPLAY:inline;BORDER-TOP-WIDTH:0px;BORDER-BOTTOM-WIDTH:0px;MARGIN-LEFT:0px;BORDER-LEFT-WIDTH:0px;MARGIN-RIGHT:0px;" title="נלקח מאתר simpleSms.co.il" border="0" alt="נלקח מאתר simpleSms.co.il" src="http://blogs.microsoft.co.il/blogs/esakal/simplesmswebserviceAPI_6DC99DA7.jpg" width="244" height="91" /&gt; &lt;/p&gt;
&lt;h2&gt;שלב 1 – פתיחת חשבון&lt;/h2&gt;
&lt;p&gt;בשלב זה נקים חשבון בחברה, נרכוש חבילת הודעות SMS, ונפעיל את התמיכה בAPI מצד SimpleSMS.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;u&gt;הרשמה לאתר&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;הכנסו &lt;a href="http://www.simplesms.co.il/" target="_blank"&gt;לאתר החברה&lt;/a&gt; וצרו משתמש חדש (פעולה זו לא עולה כסף). &lt;/li&gt;
&lt;li&gt;בחרו את חבילת ההודעות המתאימה (מחיר הודעה משתנה בהתאם לחבילה שבוחרים ונע בין 0.29 ל 0.15 אג). &lt;/li&gt;
&lt;li&gt;בצעו רכישה דרך האתר של החבילה שבחרתם. &lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;&lt;u&gt;יצירת חשבון לשימוש ב-webservice&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;בשלב זה צריכים ליצור משתמש נוסף שישמש אותנו להתממשקות לwebservice. לצערי אין אפשרות ליצור את המשתמש הנ”ל דרך האתר וחייבים לעשות זאת בשיחה מול נציג החברה או באמצעות מייל.&amp;nbsp;לא קל לתפוס אותם &amp;nbsp;אז היו סבלנים ואל תתביישו ל&amp;quot;נדנד&amp;quot; מספר פעמים ביום עד שזה יבוצע.&lt;/p&gt;
&lt;p&gt;ליצירת המשתמש - צרו קשר טלפוני ו/או בדוא”ל ובקשו:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;לפתוח חשבון webservice עבור המשתמש שיצרתם באתר. &lt;/li&gt;
&lt;li&gt;להעביר את כל ההודעות שרכשתם מהחשבון באתר לחשבון הwebservice. &lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;הנציג אמור לחזור אליכם עם &lt;u&gt;2 פרטי משתמשים חדשים&lt;/u&gt; בנוסף לזה זה שיצרתם באתר. האחד משמש לשליחת הודעות דרך הwebservice והשני לצורך כניסה למערכת ניהול הwebservice. &lt;/p&gt;
&lt;h2&gt;שלב 2 – אינטגרציה&lt;/h2&gt;
&lt;p&gt;אחרי שסיימנו עם הצד של SimpleSMS, הגיע הזמן לחבר בין האפליקציה לשירותי הwebservice. אתם מוזמנים להוריד את “&lt;a href="http://www.simplesms.co.il/webservice.asp" target="_blank"&gt;המדריך למשתמש&lt;/a&gt;” או “&lt;a href="http://www.simplesms.co.il/webservice.asp" target="_blank"&gt;חבילת דוגמאות קוד&lt;/a&gt;” מהאתר שלהם ולדלג לשלב&amp;nbsp;3 – או להמשיך לקרוא הסבר מקוצר.&lt;/p&gt;
&lt;p&gt;פתחו פרוייקט חדש/קיים והוסיפו web reference &lt;a href="http://ws2.simplesms.co.il/SendService.asmx" target="_blank"&gt;לכתובת הבאה&lt;/a&gt;&amp;nbsp;(נלקחה מאתר החברה). בחרתי לקרוא לweb reference בשם “SimpleSmsProxy” אבל אתם רשאים לבחור שם אחר אם תרצו.&lt;/p&gt;
&lt;p&gt;השתמשו בקטע קוד הבא לשליחה של הודעת SMS לטלפון סלולארי אחד או יותר&lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;&lt;pre class="brush: csharp;"&gt;public bool SendSms(string[] toMobile, string message) &lt;br /&gt;{ &lt;br /&gt;    SimpleSmsProxy.SendService service = new SimpleSmsProxy.SendService(); &lt;br /&gt;    bool sendSucceeded = service.SendBulkMessage(&amp;quot;{your username}&amp;quot;, &amp;quot;{your password}&amp;quot;, &amp;quot;{sender mobile}&amp;quot;, toMobile, message); &lt;br /&gt;&lt;br /&gt;    return sendSucceeded; &lt;br /&gt;} &lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;הערה - &lt;/strong&gt;הקפידו להשתמש בשם המשתמש והסיסמא הנכון.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;strong&gt;ריכזתי פה את ארבעת המתודות השכיחות&lt;/strong&gt; בשירות זה. היה לי חשוב להציג פה גם את המתודות שמבצעות קריאה א-סנכרונית. זה יכול להיות מאוד שימושי במצב של “שגר-ושכח” ורוב הסיכויים שבזה תשתמשו באפליקציה.&lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;&lt;pre class="brush: csharp;"&gt;public bool SendMessage(string username, string password, string fromMobile, string toMobile, string message)&lt;br /&gt;public void SendMessageAsync(string username, string password, string fromMobile, string toMobile, string message)&lt;br /&gt;public bool SendBulkMessage(string username, string password, string fromMobile, string[] toMobile, string message)&lt;br /&gt;public void SendBulkMessageAsync(string username, string password, string fromMobile, string[] toMobile, string message)&lt;/pre&gt;&lt;/div&gt;
&lt;p align="right"&gt;&lt;strong&gt;שימו לב! &lt;/strong&gt;בשלב זה ההודעות עדיין לא יישלחו בפועל לפלאפונים. זאת היות ומשתמש חדש בSimpleSMS מוגדר כברירת מחדל במצב של “בדיקות”. מברוכ למפתחי SimpleSMS על החשיבה הבריאה שנועדה לאפשר ביצוע בדיקות אינטגרציה מבלי לבזבז הודעות מהחבילה. חבל רק שזה לא מתועד באף מקום ועלה לי ביזע רב לגלות זאת. אז איך תדעו שהאינטגרציה עבדה? הכנסו ל&lt;a href="http://ws.simplesms.co.il/" target="_blank"&gt;ממשק הניהול הwebservice&lt;/a&gt; – בממשק ניתן לראות את ההודעות והסטטוס שלהם (נשלח/לא נשלח/הודעת בדיקה).&lt;/p&gt;
&lt;h2&gt;שלב 3 – יציאה ממצב בדיקות&lt;/h2&gt;
&lt;p&gt;כפי שהסברתי בסוף הסעיף הקודם, הודעות שיישלחו מהאפליקציה יגיעו לממשק הניהול בSimpleSMS ולא יישלחו לפלאפון (מצב בדיקות). כדי לצאת ממצב זה יש לבצע את הפעולות הבאות:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;הכנסו ל&lt;a href="http://ws.simplesms.co.il/" target="_blank"&gt;מערכת ניהול משתמש webservice&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;בתפריט למעלה בחרו “פרטים אישיים” –&amp;gt; “עדכון פרטי חשבון” &lt;/li&gt;
&lt;li&gt;הורידו את הV המסומן בשדה “שליחת נסיון” &lt;/li&gt;
&lt;li&gt;וודאו כי הערך של השדה “חשבון דמו” הוא “לא” &lt;/li&gt;
&lt;li&gt;שימרו את השינויים. &lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/disable_demo_199E786D.jpg"&gt;&lt;img style="BORDER-RIGHT-WIDTH:0px;DISPLAY:inline;BORDER-TOP-WIDTH:0px;BORDER-BOTTOM-WIDTH:0px;BORDER-LEFT-WIDTH:0px;" title="disable_demo" border="0" alt="disable_demo" src="http://blogs.microsoft.co.il/blogs/esakal/disable_demo_thumb_4FA5882B.jpg" width="213" height="46" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;זה הכל. המערכת אמורה לשלוח הודעות. נסו בעצמכם. &lt;/p&gt;
&lt;h2&gt;מילות סיכום&lt;/h2&gt;
&lt;p&gt;במאמר זה ראינו איך ניתן במספר שלבים פשוטים לבצע שליחה של הודעות SMS מאפליקציות .net לטלפונים סלולארים. הדגמתי איך לעשות זאת בעזרת חברת “Simple SMS” אבל אני חייב להודות שלמרות פשטות העבודה מולם הם לא הבחירה המועדפת עלי בגלל חסרונותיה שרשומים למטה. בפרויקט בינוני/גדול אני ממליץ לבחון ראשית את החברות הנוספות ורק אז להחליט מי הכי מתאימה עבורכם. עבור פיתוחים מהירים/בייתים/POC השירות שלהם מספק בהחלט.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;u&gt;&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;u&gt;יתרונות “Simple SMS”&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;מתאים לפיתוחים אישיים – תהליך הרישום פשוט ולא דורש שיחות והסברים מול החברה. &lt;/li&gt;
&lt;li&gt;מדריך למשתמש פשוט וברור כולל דוגמאות קוד בשפות שונות לצורך התממשקות למערכת ושליחת הודעות. &lt;/li&gt;
&lt;li&gt;ממשק ניהול פשוט ונוח המאפשר מעקב אחר משלוח הודעות, רכישת חבילות וכו’. &lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;&lt;u&gt;חסרונות “Simple SMS”&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;זמינות, זמינות, זמינות – קיים קושי רב ביצירת קשר עם נציג אמיתי (לא מוקדן) לקבלת שירות ו/או תמיכה טכנית. &lt;/li&gt;
&lt;li&gt;אבטחה - עושה רושם כי אין להם &lt;a href="http://en.wikipedia.org/wiki/Transport_Layer_Security" target="_blank"&gt;SSL Certificate&lt;/a&gt;. אני רושם זאת בהיסוס קל היות ושלחתי אליהם מייל בנושא ולמרבה ה”הפתעה” עד כה לא קיבלתי תשובה. אז אני נותן להם קרדיט קטן שאולי יש להם והם מצניעים זאת מסיבה לא ברורה :). &lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;כפי שציינתי בתחילת הפוסט, אעלה עדכון קצר בהמשך לאחר שאתממשק ל”שמיר מערכות”.&lt;/p&gt;
&lt;p&gt;ערן&lt;/p&gt;&lt;/div&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=682219" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/Integration/default.aspx">Integration</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/Communication/default.aspx">Communication</category></item><item><title>Multi-Thread in a nutshell</title><link>http://blogs.microsoft.co.il/blogs/esakal/archive/2010/07/15/multi-thread-in-a-nutshell.aspx</link><pubDate>Thu, 15 Jul 2010 19:07:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:679384</guid><dc:creator>Eran Sakal</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.microsoft.co.il/blogs/esakal/archive/2010/07/15/multi-thread-in-a-nutshell.aspx#comments</comments><description>&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;אם אתם מתכנתים אפליקציות web לאינטרנט – אתם נמצאים בסביבה מרובת משתמשים וזה אומר שאתם צריכים לדעת להגן על משאבים משותפים. &lt;/p&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;היות ונושא פיתוח אפליקציות לסביבות מרובות משתמשים הוא מורכב וגדול, בלתי אפשרי לסכם אותו בפוסט אחד. לכן השתדלתי בפוסט זה להציג את הנושאים שמתאימים ל-90% מהפיתוחים.&lt;/p&gt;&lt;!--more--&gt;
&lt;h2 style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;טרמינולוגיה &lt;/h2&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;סעיף זה מרכז מושגים שיופיעו בפוסט. אין צורך להתעמק בשלב זה במושגים, לאחר קריאת הפוסט הם יהיו ברורים יותר.&lt;/p&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;Request = גלישה על-ידי משתמש לעמוד באתר. אם נתייחס לדפדפנים השכיחים המכילים Tabs, כל Tab בדפדפן שגולש לעמוד באתר הינו Request.&lt;/p&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;Thread = מבלי להכנס לדקויות כל גלישה לעמוד באתר (כל Request) מתבצע בThread משלו. אז ניתן להגיד שכל Request שווה לפחות Thread אחד נפרד.&lt;/p&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;Resource = משאב באתר. המילה משאב מתייחסת גם לdatabase, קבצי מערכת ועוד. במאמר זה נתמקד במשאבים מסוג משתנים משותפים.&lt;/p&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;MultiThreaded environment = סביבה מרובת משתמשים (לדוגמא אתרי web שמאפשר גלישה של עשרות עד אלפי משתמשים בשניה).&lt;/p&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;Thread-Safe = קוד שפותח תוך הקפדה על עקרונות פיתוח בסביבה מרובת משתמשים ומנהל נכון משאבים משותפים.&lt;/p&gt;
&lt;h2&gt;רגע לפני שמתחילים&lt;/h2&gt;
&lt;p&gt;multi-threading מתחלק ל-2 נושאים מרכזיים:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;פיתוח אפליקציות שיבצעו פעולות בצורה מקבילית (Multi-threaded application). &lt;/li&gt;
&lt;li&gt;בהנתן שהאפליקציה שלך מבצעת פעולות בו-זמנית או פועלת בסביבת מרובת משתמשים – ניהול נכון של המשאבים המשותפים.&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;היות וכל מי שכותב בasp.net כותב בסביבה מרובת משתמשים גם אם הוא לא מודע לכך - בחרתי לכתוב בפוסט זה על הנושא השני. בסוף המאמר צירפתי קישורים למאמרים מפורטים המתייחסים גם לנושא הראשון.&lt;/p&gt;
&lt;h1 style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;הגדרה של משאב משותף&lt;/h1&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;משאב משותף הינו משאב שניתן להגיע אליו בו-זמנית ממספר threads על-ידי מספר גולשים. דוגמא טובה לזה ניתן למצוא באתר ויקיפדיה. אם תכנסו &lt;a href="http://he.wikipedia.org/wiki/%D7%A4%D7%99%D7%A0%D7%92%D7%95%D7%95%D7%99%D7%A0%D7%99%D7%9D" target="_blank"&gt;לקישור הבא&lt;/a&gt; תראו מידע על פינגווינים. מידע זה נגיש לכל מי שגולש לעמוד. בחלק העליון של העמוד יש כפתור “עריכה” שמאפשר לגולשים לערוך את המידע. עריכה של המידע תשפיע על כל שאר הגולשים שצופים בעמוד. מידע זה עונה להגדרה של משאב משותף היות והמידע הזה משותף לכל מי שגולש לעמוד. ייתכן שהמידע הזה נשלף מבסיס נתונים ואז בסיס הנתונים הינו המשאב המשותף. ייתכן והמידע נשלף מתוך אובייקט שנמצא בזיכרון של השרת ואז האובייקט הזה הינו משאב משותף.&lt;/p&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;דוגמאות לאובייקטים שעונים על ההגדרה:&lt;/p&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;
&lt;ul&gt;
&lt;li&gt;משתנים סטטים (static members). &lt;/li&gt;
&lt;li&gt;אובייקטים שנשמרים ברמת Application/Session. &lt;/li&gt;
&lt;li&gt;אובייקטים שנשמרים בתשתית Cache כלשהי. &lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;
&lt;h1 style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;מדוע צריך לנהל גישה למשאב משותף&lt;/h1&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;נסתכל על הדוגמא הבאה. נניח וכתבנו מנגנון שמאפשר לגולשים לקבל קופונים. בדוגמא זו אין מגבלה על כמות הקופונים לחלוקה. כאשר גולש מבקש לקבל קופון יתבצעו 2 פעולות - בדיקה אם נשארו קופונים ואם כן שליחה של הקופון לגולש. נניח מצב שבו 2 גולשים מבקשים קופון בו-זמנית. המחשב יכול לטפל ב-2 הבקשות באחת מהדרכים הבאות (אין לנו שליטה כרגע על בחירת המחשב):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;לטפל בגולש א’ ולאחר מכן בגולש ב’&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;לטפל בגולש ב’ ולאחר מכן בגולש א’&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;לטפל במקביל ב-2 הגולשים.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;התרשים הבא מראה דוגמא למצב שבו המחשב מבצע טיפול במקביל ב-2 הגולשים (לחץ על התרשים להגדלה).&lt;/p&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;&lt;strong&gt;&lt;em&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/DIAGRAM1_2B53DD78.jpg" target="_blank"&gt;&lt;img style="BORDER-RIGHT-WIDTH:0px;DISPLAY:inline;BORDER-TOP-WIDTH:0px;BORDER-BOTTOM-WIDTH:0px;BORDER-LEFT-WIDTH:0px;" title="אין מגבלה של קופונים" border="0" alt="אין מגבלה של קופונים" src="http://blogs.microsoft.co.il/blogs/esakal/DIAGRAM1_thumb_24C80FFB.jpg" width="537" height="279" /&gt;&lt;/a&gt; &lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;כאשר: &lt;/p&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;שני הגולשים מבקשים לקבל קופון באותו הזמן.&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;רצף הפעולות שביצע המחשב: פעולה 1 – בדיקה אם נשאר קופון עבור גולש א’. פעולה 2 – בדיקה אם נשאר קופון עבור גולש ב’. פעולה 3 – שליחת קופון לגולש א’. פעולה 4 – שליחת קופון לגולש ב’.&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;היות וכמות הקופונים לא מוגבלת אין צורך בפעולה כלשהי של כתיבה ואין חשש למצב שבו יתקבלו נתונים שגויים.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;נמשיך לדוגמא נוספת. בדוגמא זו כמות הקופונים מוגבלת. מכאן שבמידה וגולש כלשהו מקבל קופון, יורד המספר הכללי של הקופונים האפשרים לחלוקה באתר. לצורך כך נבצע בדיקה אם נשארו קופונים. במידה ונשארו נפחית את מספר הקופונים באחד ונשלח את הקופון לגולש. מה הבעיה שיכולה לקרות? נניח בדוגמא זו שנשאר רק קופון אחד לחלוקה. ראינו למעלה כי אין לנו שליטה על סדר הפעולות שיבצע המחשב ולכן שוב ייתכן מצב שבו המחשב יטפל ב-2 הגולשים כפי שניתן לראות בתרשים (לחץ על התרשים להגדלה).&lt;/p&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;&lt;strong&gt;&lt;em&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;&lt;strong&gt;&lt;em&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/DIAGRAM2_56560E41.jpg" target="_blank"&gt;&lt;img style="BORDER-RIGHT-WIDTH:0px;DISPLAY:inline;BORDER-TOP-WIDTH:0px;BORDER-BOTTOM-WIDTH:0px;BORDER-LEFT-WIDTH:0px;" title="מספר מוגבל של קופונים - ללא שליטה בסדר הפעולות" border="0" alt="מספר מוגבל של קופונים - ללא שליטה בסדר הפעולות" src="http://blogs.microsoft.co.il/blogs/esakal/DIAGRAM2_thumb_14E07D4A.jpg" width="537" height="404" /&gt;&lt;/a&gt; &lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;כאשר:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;שני הגולשים מבקשים לקבל קופון באותו הזמן.&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;רצף הפעולות שביצע המחשב: פעולה 1 – בדיקה אם נשאר קופון עבור גולש א’. מחזיר תשובה חיובית (נשאר קופון 1). פעולה 2 – בדיקה אם נשאר קופון עבור גולש ב’. מחזיר תשובה חיובית (כרגע מבחינת המחשב עדיין נשאר קופון 1). פעולה 3 – הורדת מספר הקופונים באחד (הקופון שיישלח לגולש א’) - נשאר במערכת 0 קופונים. פעולה 4 – הורדת מספר הקופונים באחד (הקופון שיישלח לגולש ב’). שלב זה שגוי שכן אין יותר קופונים! אבל היות והבדיקה נעשתה לפני ההחסרה של מספר הקופונים עבור גולש א’&amp;nbsp; מספר הקופונים יהיה 1-. פעולות 5 ו-6 – שליחת קופונים לגולש א’ וגולש ב’.&amp;nbsp; יוצא&amp;nbsp; שחילקנו קופון שלא קיים לגולש ב’.&amp;nbsp; &lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;קיבלנו מצב שגוי והפסדנו קופון ששלחנו לגולש ב’ למרות שלא נשארו יותר קופונים.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;מה היה קורה אם 200 איש היו מבקשים בו זמנית את הקופון? לפי הדוגמא למעלה ניתן לראות כי במצב תיתכן חלוקה של עד 199 קופונים יותר מהמתוכנן. &lt;/p&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;&lt;strong&gt;מה הפתרון למצב זה? &lt;/strong&gt;כדי לפתור מצב זה צריך להתייחס לשלושת השלבים (הבדיקה, החסרת מספר הקופונים ושליחת הקופון) כפעולה אחת. צריך להורות למחשב לטפל כל פעם בגולש אחד בלבד. בדוגמא למעלה אם הפעולות היו מבוצעות ברצף לכל גולש אז גולש א’ היה מקבל את הקופון וגולש ב’ היה מקבל הודעה שלא נשארו יותר קופונים. בפוסט זה נלמד כיצד ניתן להורות למחשב לגרום לגולש ב’ להמתין עד שגולש א’ יסיים להריץ את כל שלושת הפעולות. התרשים הבא מראה כיצד זה יבוצע (לחץ על התרשים להגדלה).&lt;/p&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/DIAGRAM3_56111752.jpg" target="_blank"&gt;&lt;img style="BORDER-RIGHT-WIDTH:0px;DISPLAY:inline;BORDER-TOP-WIDTH:0px;BORDER-BOTTOM-WIDTH:0px;BORDER-LEFT-WIDTH:0px;" title="מספר מוגבל של קופונים - שליטה בסדר הפעולות" border="0" alt="מספר מוגבל של קופונים - שליטה בסדר הפעולות" src="http://blogs.microsoft.co.il/blogs/esakal/DIAGRAM3_thumb_7FAA03E7.jpg" width="604" height="454" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h1&gt;דרכים לניהול משאבים משותפים (כתיבת קוד Thread-Safe)&lt;/h1&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;בסעיפים למעלה ראינו שחשוב לנהל בצורה מבוקרת גישה למשאב משותף כדי להמנע ממצבים לא מתוכננים. בסעיפים הבאים נראה כיצד מבצעים זאת בשפה #C.&lt;/p&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;קוד שמוגדר כThread-Safe הינו קוד שהמתכנת לקח בחשבון מצבים של קריאה-כתיבה בו זמנית למשאבים שהוא משתמש בהם. בסעיף זה נראה מספר תרחישים ואת הכלים העומדים לרשותנו לפתרון התרחיש.&lt;/p&gt;
&lt;h2 style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;תרחיש ראשון – קריאה-כתיבה בו זמנית (הכי שכיח)&lt;/h2&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;תרחיש זה פותר את בעיית הקופונים שכתבתי למעלה. בתרחיש זה יש לנו מספר פעולות שאנחנו רוצים שיקרו ברצף ושלא תהיה אפשרות ל-2 גולשים לבצע במקביל את הפעולה. כדי לעשות זאת נשתמש במנגנון מסוג lock.&lt;/p&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;נסתכל על הקוד הבא (כרגע לא מטפל בסוגיית הThread-Safe):&lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;
&lt;div style="PADDING-BOTTOM:0px;MARGIN:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;FLOAT:none;PADDING-TOP:0px;" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:42007683-fb31-403c-818b-63e5520f9286" class="wlWriterEditableSmartContent"&gt;&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; "&gt;private int m_couponsLeft;

public string GetCoupon()
{
    if (m_couponsLeft &amp;gt; 0)
    {
        m_couponsLeft--;
        return &amp;quot;193445023&amp;quot;; // Dummy Coupon Number
    }
    else
    {
        return string.Empty;
    }
}

private bool HasMoreCoupons()
{
    return (m_couponsLeft &amp;gt; 0);
}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;כאשר:&lt;/p&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;
&lt;ul&gt;
&lt;li&gt;המשאב המשותף במקרה הזה הוא המשתנה “m_couponsLeft”. &lt;/li&gt;
&lt;li&gt;שורה 3 – מגדירה מתודה שמחזירה קופונים במידה ונשארו (מתודה זו מבצעת קריאה וכתיבה למשאב המשותף). &lt;/li&gt;
&lt;li&gt;שורה 5 – בודקת אם נשארו קופונים מול המשאב המשותף (המשתנה m_couponsLeft). &lt;/li&gt;
&lt;li&gt;שורה 7 – מחסירה באחד את מספר הקופונים שנשארו. &lt;/li&gt;
&lt;li&gt;שורה 8 – נקראת במידה ונשארו קופונים. מחזירה את מספר הקופון. &lt;/li&gt;
&lt;li&gt;שורה 12 – נקראת במידה ולא נשארו קופונים – מחזירה ערך ריק. &lt;/li&gt;
&lt;li&gt;שורה 16 – מגדירה מתודה שמבצעת בדיקה בלבד אם נשארו קופונים (מתודה זו מבצעת קריאה בלבד מהמשאב המשותף). &lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;
&lt;p&gt;מה יקרה אם 2 גולשים שונים יקראו בו-זמנית למתודה “GetCoupon” כאשר מספר הקופונים הנותרים הוא 1? אם התשובה לא קופצת לך מיד בראש – קרא שוב את הסעיף “מדוע צריך לנהל משאב משותף”. &lt;/p&gt;
&lt;p&gt;כדי לפתור את הבעיה נבצע שינוי קטן של המתודה “GetCoupon”. נסתכל על הקוד הבא:&lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;
&lt;div style="PADDING-BOTTOM:0px;MARGIN:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;FLOAT:none;PADDING-TOP:0px;" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:a3b1bb21-b70c-4bb5-aafb-507193421c20" class="wlWriterEditableSmartContent"&gt;&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; "&gt;private int m_couponsLeft;
private object m_couponLockObj = new object();

public string GetCoupon()
{
    lock (m_couponLockObj)
    {
        if (m_couponsLeft &amp;gt; 0)
        {
            m_couponsLeft--;
            return &amp;quot;193445023&amp;quot;; // Dummy Coupon Number
        }
        else
        {
            return string.Empty;
        }           
    }        
}

private bool HasMoreCoupons()
{
    lock (m_couponLockObj)
    {
        return (m_couponsLeft &amp;gt; 0);   
    }        
}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;כאשר:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;שורה 2 – מגדירה אובייקט שכל מטרתו לנהל את הגישה למשאב המשותף&amp;nbsp; &lt;/li&gt;
&lt;li&gt;שורות 6 ו22&amp;nbsp; – שורות אלו מבצעות את הנעילה בפועל. הפקודה lock מתבצעת על האובייקט שהוגדר בשורה 2 ומתבצעת לפני פניה למשאב המשותף (m_couponsLeft). &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;פרוש הפקודה lock היא : בדוק אם האובייקט שהועבר אליך נעול על-ידי משתמש אחר, אם לא - נעל אותו והמשך הלאה. אם הוא נעול על-ידי משתמש אחר - המתן עד שהוא ישתחרר ואז נעל אותו והמשך הלאה. קיבלנו פה מנגנון שמאפשר “בלעדיות” על אובייקט.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;איך זה משרת את הצורך? עכשיו ניתן לדעת בוודאות שהפעולות יתבצעו לפי סדר הקריאה. אם בוצעה קריאה בו זמנית למתודה, הגולש שקרא לה ראשון ישיג את ה”בלעדיות” ויקבל את הקופון. הגולש השני ימתין עד שתשתחרר הנעילה ורק אז יבצע את הבדיקה ובמקרה שלנו יקבל הודעה שלא נשארו קופונים.&lt;/p&gt;
&lt;h3&gt;מספר דגשים חשובים:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;את הנעילה מבצעים על אובייקט מסוג reference-type כאשר מומלץ שזה לא יהיה האובייקט שאותו מנהלים. ספציפית בדוגמה שנתתי פה לא יכולתי לנעול את המשאב עצמו היות והוא מסוג value-type אבל גם אם כן לא הייתי מבצע עליו נעילה. &lt;/li&gt;
&lt;li&gt;מיד אחרי הפקודה lock מגדירים סוגריים מסולסלים. זהו הScope של הנעילה. ברגע שיוצאים מהתיחום של הסוגריים (שורה 17) הנעילה משתחררת אוטומטית. השיחרור האוטומי יקרה גם במצב של Exception שנזרק בתוך הסוגריים או במצב של return (מצב נוכחי). &lt;/li&gt;
&lt;li&gt;יש הרבה דוגמאות קוד באינטרנט שמראות שימוש בlock על האובייקט this במקום על אובייקט אחר, לצורך העניין שורה 6 תכיל את הקוד &lt;span&gt;lock(this);&lt;/span&gt;. מצב זה לא תקין, יכול להוביל ל&lt;a href="http://he.wikipedia.org/wiki/%D7%A7%D7%99%D7%A4%D7%90%D7%95%D7%9F_(%D7%9E%D7%93%D7%A2%D7%99_%D7%94%D7%9E%D7%97%D7%A9%D7%91)" target="_blank"&gt;dead-lock&lt;/a&gt; ולכן יש להמנע מלהשתמש בו. ניתן &lt;a href="http://www.google.co.il/search?hl=iw&amp;amp;q=c%23+lock+this&amp;amp;meta=&amp;amp;aq=f&amp;amp;aqi=g10&amp;amp;aql=&amp;amp;oq=&amp;amp;gs_rfai=&amp;amp;gs_upl=4623,176,10,1,58,578,1,5:1" target="_blank"&gt;לגגל על נושא זה&lt;/a&gt;. &lt;/li&gt;&lt;/ul&gt;
&lt;h2&gt;תרחיש שני – קריאה מרובה למשאב וכתיבה מועטה לאותו המשאב&lt;/h2&gt;
&lt;p&gt;המנגנון הבא הינו אופטימיזציה של מנגנון ה-lock שראינו בסעיף הקודם. נשתמש באותה דוגמא מהסעיף הקודם אבל נוסיף מידע נוסף. נניח וידוע לנו שתדירות הקריאה למתודה “HasMoreCoupons” גדולה בהרבה מתדירות הקריאה למתודה “GetCoupon”. במצב כזה שימוש בlock פוגם לנו בביצועים. מדוע?&lt;/p&gt;
&lt;p&gt;הפגיעה בביצועים נגרמת היות והמנגנון lock הוא טורי, רק אחד רשאי לבצע בכל פעם את הקוד שבתוך הlock. נסתכל על המתודה “HasMoreCoupons”. במתודה זו אנחנו מבצעים קריאה בלבד מהמשאב (אין כתיבה למשאב במתודה). אם יש מאתיים פעולות קריאה למתודה הן יתבצעו אחת אחרי השניה. אבל מהסעיפים הקודמים למדנו שאין בעיה של Thread-Safe במצב של קריאה בו-זמנית. הבעיה היא רק במצב של כתיבה בו-זמנית או קריאה וכתיבה בו זמנית. &lt;/p&gt;
&lt;p&gt;על-מנת לתמוך בתרחיש זה נשתמש ברכיב שנקרא ReaderWriterLockSlim. נסתכל על הקוד הבא:&lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;
&lt;div style="PADDING-BOTTOM:0px;MARGIN:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;FLOAT:none;PADDING-TOP:0px;" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:5f56de0b-f127-4452-88c9-07e1862be75e" class="wlWriterEditableSmartContent"&gt;&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; "&gt;private int m_couponsLeft;
private ReaderWriterLockSlim m_couponLockObj = new ReaderWriterLockSlim();

public string GetCoupon()
{
    try
    {
        m_listLocker.EnterWriteLock();

        if (m_couponsLeft &amp;gt; 0)
        {
            m_couponsLeft--;
            return &amp;quot;193445023&amp;quot;; // Dummy Coupon Number
        }
        else
        {
            return string.Empty;
        }    
    }
    finally
    {
        m_listLocker.ExitWriteLock();
    }        
}

private bool HasMoreCoupons()
{
    try
    {
        m_listLocker.EnterReadLock();

        return (m_couponsLeft &amp;gt; 0);   
    }
    finally
    {
        m_listLocker.ExitReadLock();
    }     
}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;כאשר:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;קיבלנו הפרדה בקוד בין מצבים בהם מבצעים רק קריאה למשאב לבין מצבים בהם מבצעים גם כתיבה למשאב. &lt;/li&gt;
&lt;li&gt;שורה 2 – מגדירה אובייקט מסוג “ReaderWriterLockSlim” באמצעותו ננהל את הגישה למשאב המשותף. &lt;/li&gt;
&lt;li&gt;שורה 8 – מודיעה לאובייקט כי הקוד הבא מבצע &lt;u&gt;כתיבה&lt;/u&gt; למשאב. &lt;/li&gt;
&lt;li&gt;שורה 22 – מודיעה לאובייקט כי הקוד סיים לבצע את הכתיבה למשאב. &lt;/li&gt;
&lt;li&gt;שורה 30– מודיעה לאובייקט כי הקוד הבא מבצע &lt;u&gt;קריאה &lt;/u&gt;למשאב &lt;/li&gt;
&lt;li&gt;שורה 36– מודיעה לאובייקט כי הקוד סיים לבצע את הקריאה למשאב. &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;איך זה משרת את הצורך? המנגנון ReaderWriterLockSlim מאפשר טיפול במקביל (בו-זמנית) בפעולות שננעלו לקריאה (שורה 30) כל עוד לא בוצעה בקשה לנעילה של כתיבה למשאב. ברגע שתורץ שורה 8 (בקשת “בלעדיות” לכתיבה למשאב), לא יתאפשר יותר נעילות לצורך קריאה (שורה 30). בקשות אלו יתווספו לתור המתנה. לאחר סיום טיפול בכל נעילות הקריאה שהתחילו לפני הבקשה לנעילת כתיבה , תתבצעה פעולת הכתיבה. לאחר סיום פעולת הכתיבה יבוצעו כל הבקשות לקריאה שנשמרו בתור ההמתנה.&lt;/p&gt;
&lt;h3&gt;מספר דגשים חשובים:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;בתרחיש שבו מרבית הפעולות על המשאב הינן פעולות קריאה קיבלנו אופטימיזציה מעולה מבחינת ביצועים שכן פעולות קריאה יבוצעו בצורה מקבילית. &lt;/li&gt;
&lt;li&gt;שימו לב לסיומת של שם המחלקה – ReaderWriterLock&lt;strong&gt;&lt;u&gt;Slim&lt;/u&gt;&lt;/strong&gt; (קיים אובייקט עם שם זהה בלי הסיומת Slim). &lt;/li&gt;
&lt;li&gt;חובה להשתמש ב - try…finally ולוודא שכותבים את השחרור של הנעילה בfinally. אחרת מספיק Exception אחד כדי ליצור מצב מצב של &lt;a href="http://he.wikipedia.org/wiki/%D7%A7%D7%99%D7%A4%D7%90%D7%95%D7%9F_(%D7%9E%D7%93%D7%A2%D7%99_%D7%94%D7%9E%D7%97%D7%A9%D7%91)" target="_blank"&gt;dead-lock&lt;/a&gt;. &lt;/li&gt;&lt;/ul&gt;
&lt;h2&gt;תרחיש שלישי – פעולות על משתנה בודד &lt;/h2&gt;
&lt;p&gt;בדוגמאות הקודמות ראינו כיצד לבצע נעילה על מספר שורות קוד. מה בנוגע למצבים בהם מתבצעת פעולה על משתנה בודד (שורת קוד אחת)? האם עדיין צריך לנהל אותו כמשאב משותף? &lt;/p&gt;
&lt;p&gt;נבחן את הדוגמא הבאה.&amp;nbsp; יש לנו משתנה מסוג int שסופר כניסות לאתר. האם הפעולה הבאה לדעתך היא Thread-Safe?&lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;
&lt;div style="PADDING-BOTTOM:0px;MARGIN:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;FLOAT:none;PADDING-TOP:0px;" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:668f4bdb-7413-48ee-8d06-8d40af344a64" class="wlWriterEditableSmartContent"&gt;&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; "&gt;requestCounter++;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;למרבה ההפתעה התשובה לכך היא לא. זאת היות והשורה הנ”ל מתורגמת על-ידי המחשב ל-3 פקודות מכונה. הסבר טוב לכך נמצא &lt;a href="http://thith.blogspot.com/2005/11/c-interlocked.html" target="_blank"&gt;בפוסט הבא&lt;/a&gt;. כדי להתגבר על הבעיה ניתן אומנם להשתמש בשיטות שלמדנו למעלה אבל זה אומר שנצטרך לרשום הרבה שורות קוד רק כדי להגן על פעולה פשוטה יחסית של העלאת ערך משתנה ב-1 (שורה אחת).&lt;/p&gt;
&lt;p&gt;כדי לפשט את העניין קיים האובייקט “Interlocked” שיושב תחת הnamespace הבא - “System.Threading”. בעזרתו ניתן לכתוב את השורה למעלה בצורה הבאה:&lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;
&lt;div style="PADDING-BOTTOM:0px;MARGIN:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;FLOAT:none;PADDING-TOP:0px;" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:0193310f-9b4d-4425-8a48-ad3df7efd5bd" class="wlWriterEditableSmartContent"&gt;&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; "&gt;Interlocked.Increment(ref requestCounter);&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;אני לא אכנס להסבר על אובייקט זה היות &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.interlocked.aspx" target="_blank"&gt;והתיעוד שלו בMSDN&lt;/a&gt; פשוט וברור. &lt;/p&gt;
&lt;h2&gt;תרחיש רביעי (ואחרון) – איתחול משאב משותף&lt;/h2&gt;
&lt;p&gt;נניח ויש לנו משתנה שאותו אנחנו צריכים לאתחל. מה יקרה אם מספר גולשים בו זמנית יאתחלו את האובייקט? &lt;/p&gt;
&lt;p&gt;נסתכל על הקוד הבא:&lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;
&lt;div style="PADDING-BOTTOM:0px;MARGIN:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;FLOAT:none;PADDING-TOP:0px;" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:221d0da5-2a95-4dce-8ebb-856a7ef593ec" class="wlWriterEditableSmartContent"&gt;&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; "&gt;private DataManager m_manager = null;

public DataManager GetManager()
{
    if (m_manager == null)
    {
        m_manager = new DataManager();
    }

    return m_manager;
}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;כאשר:&lt;/p&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;
&lt;ul&gt;
&lt;li&gt;שורה 3 – מגדירה מתודה שאחראית להחזיר אובייקט מסוג DataManager (משאב משותף). &lt;/li&gt;
&lt;li&gt;שורה 5 – בודקת אם האובייקט כבר מאותחל. &lt;/li&gt;
&lt;li&gt;שורה 7 – במידה והאובייקט לא אותחל עדיין שורה זו נקראת ומאתחלת אותו. &lt;/li&gt;
&lt;li&gt;שורה 10 – מחזירה את האובייקט מסוג DataManger. &lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;
&lt;p&gt;אני מניח שבשלב זה כבר ברורה הבעיה בקוד זה. כדי לפתור את הבעיה נשתמש ב&lt;a href="http://he.wikipedia.org/wiki/%D7%AA%D7%91%D7%A0%D7%99%D7%AA_%D7%A2%D7%99%D7%A6%D7%95%D7%91" target="_blank"&gt;“Design Pattern”&lt;/a&gt; מסוג Singleton. מדובר בתבנית שמדגימה איך צריך לאתחל משאב משותף בסביבה מרובת משתמשים. אני מצרף &lt;a href="http://devhood.com/tutorials/tutorial_details.aspx?tutorial_id=486" target="_blank"&gt;קישור למאמר באינטרנט&lt;/a&gt; שנותן הסבר טוב לנושא. בנוסף ניתן למצוא בקלות הסברים נוספים &lt;a href="http://www.google.com/search?hl=en&amp;amp;q=singleton+c%23" target="_blank"&gt;בעזרתו האדיבה של גוגל&lt;/a&gt;.&lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style="PADDING-BOTTOM:0px;MARGIN:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;FLOAT:none;PADDING-TOP:0px;" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:22eebc33-d113-4181-bd9f-ea19424e3621" class="wlWriterEditableSmartContent"&gt;&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; "&gt;private DataManager m_manager = null;
private object m_managerLock = new object();

public DataManager GetManager()
{
    if (m_manager == null)
    {
        lock (m_managerLock)
        {
            if (m_manager == null)
            {
                m_manager = new DataManager();
            }
        }
    }

    return m_manager;
}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;כאשר:&lt;/p&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;
&lt;ul&gt;
&lt;li&gt;שורה 4 – מגדירה מתודה שאחראית להחזיר אובייקט מסוג DataManager (משאב משותף). &lt;/li&gt;
&lt;li&gt;שורה 6 – בודקת אם האובייקט כבר מאותחל. &lt;/li&gt;
&lt;li&gt;שורה 8&amp;nbsp; – במידה והאובייקט לא אותחל עדיין שורה זו נקראת ומבקשת “בלעדיות” לצורך איתחול המשאב. &lt;/li&gt;
&lt;li&gt;שורה 10 – לאחר קבלת הבלעדיות מבצעים בדיקה נוספת לוודא שעדיין לא אותחל האובייקט. &lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h1&gt;מתי צריך לנהל גישה למשאב משותף&lt;/h1&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;סעיף זה מרכז רשימה של מקרים בהם נצטרך לנהל גישה למשאב משותף. &lt;/p&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;&lt;strong&gt;צריך &lt;/strong&gt;לנהל גישה כאשר:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;עובדים בסביבה מרובת משתמשים (לדוגמא אתר באינטרנט) ויש מצב ששני Threads יקראו לאותו המשאב.&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;מעורבת פעולה של כתיבה למשאב המשותף.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;&lt;strong&gt;לא צריך &lt;/strong&gt;לנהל גישה כאשר:&lt;/p&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;מבצעים רק פעולות של קריאה מהמשאב המשותף&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;כאשר מבצעים קריאה למתודה (מתודה לא נחשבת כמשאב משותף - יוסבר בהמשך סעיף זה)&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;כאשר מבצעים קריאה למשתנים שהscope שלהם הוא מתודה (יוסבר בהמשך סעיף זה).&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;
&lt;h2&gt;האם צריך לנהל מצב שבו קוראים למתודה&lt;/h2&gt;
&lt;p&gt;תשובה מהירה – לא! מבלי להכנס לפרטים טכנים, כשקוראים למתודה מבצעים &lt;strong&gt;&lt;u&gt;קריאה&lt;/u&gt;&lt;/strong&gt; למקום כלשהו בזיכרון שמכיל את הפקודות שמרכיבות את המתודה. היות ולא מעורבת פעולה של כתיבה אין צורך להגן על קריאה למתודה.&lt;/p&gt;
&lt;h2&gt;האם משתנים שהscope שלהם הוא מתודה דורשים הגנה&lt;/h2&gt;
&lt;p&gt;תשובה מהירה – לא! שוב מבלי להכנס לפרטים טכנים, עבור כל מתודה שמורצת מוקצה איזור בזיכרון. באיזור זה נשמרים כל המשתנים ששייכים למתודה. המתודה הבאה מכילה 2 משתנים (rand ו-result). אם לדוגמא 2 גולשים יקראו למתודה הבאה בו-זמנית,לא תהיה בעיה מבחינת MultiThread היות ולכל מתודה יוקצה מקום משלו בזיכרון ויאותחל עבורו המשתנים בנפרד.&lt;/p&gt;
&lt;div style="TEXT-ALIGN:left;DIRECTION:ltr;"&gt;
&lt;div style="PADDING-BOTTOM:0px;MARGIN:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;FLOAT:none;PADDING-TOP:0px;" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:9a24e22c-679e-492e-9da6-38597e65d6ae" class="wlWriterEditableSmartContent"&gt;&lt;pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; "&gt;public int doSomething()
{
    Random rand = new Random();
    int result = rand.Next();
    return result;
}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h1&gt;כיצד ניתן לדעת אם מתודה מסויימת היא Thread-Safe&lt;/h1&gt;
&lt;p&gt;בסעיף הקודם ראינו שקריאה למתודה לא דורשת הגנה של Multi-Thread. אם כך מדוע צריך לבדוק אם מתודה היא Thread-Safe? התשובה לכך היא שכאשר מציינים שמתודה היא Thread-Safe מתכוונים שהיא תוכנתה על-בסיס עקרונות של סביבת מרובת משתמשים והיא מנהלת משאבים משותפים בצורה שהיא Thread-Safe.&lt;/p&gt;
&lt;p&gt;כדי לדעת אם מתודה היא Thread-Safe צריך לפנות לתיעוד של המחלקה הרלוונטית. לצורך דוגמה נסתכל על המתודה Add של המחלקה הגנרית &lt;span&gt;“System.Collections.Generic.List”&lt;/span&gt;. כדי לדעת שהמתודה Add של המחלקה List היא לא Thread-Safe נכנסים &lt;a href="http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx" target="_blank"&gt;לקישור הבא בMSDN&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;התצלום הבא נלקח מMSDN. בקישור קיים סעיף שנקרא Thread Safety. סעיף זה מופיע לרוב לקראת סוף התיעוד של כל מחלקה שמכבדת את עצמה (או את מתכנתיה).&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/esakal/threadsafty_4532007A.jpg" target="_blank"&gt;&lt;img style="BORDER-RIGHT-WIDTH:0px;DISPLAY:inline;BORDER-TOP-WIDTH:0px;BORDER-BOTTOM-WIDTH:0px;BORDER-LEFT-WIDTH:0px;" title="thread-safty" border="0" alt="thread-safty" src="http://blogs.microsoft.co.il/blogs/esakal/threadsafty_thumb_5B5C09FE.jpg" width="644" height="77" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;הדגשתי בקו אדום את המשפט שאומר שכל קריאה לmember (ומכאן גם למתודות) של מופע (Instance) של המחלקה לא מוגן בהקשר של thread-safe.&lt;/p&gt;
&lt;h1&gt;&lt;strong&gt;לסיכום&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;בפוסט זה רשמתי את העקרונות הבסיסיים אך חשובים עד מאוד של פיתוח בסביבה מרובת משתמשים. אני ממליץ בחום &lt;a href="http://www.google.co.il/#hl=iw&amp;amp;source=hp&amp;amp;q=c%23+multithreading&amp;amp;meta=&amp;amp;aq=f&amp;amp;aqi=&amp;amp;aql=&amp;amp;oq=&amp;amp;gs_rfai=&amp;amp;gs_upl=127%2C127%2C1%2C0%2C0%2C0%2C&amp;amp;fp=955bbd0c16470e5a" target="_blank"&gt;לגגל על נושא זה באינטרנט&lt;/a&gt;. תרגישו חופשי לשלוח שאלות אלי או לכתוב שאלות &lt;a href="http://www.tapuz.co.il/Forums2008/ForumPage.aspx?ForumId=831&amp;amp;r=1" target="_blank"&gt;בפורום בתפוז&lt;/a&gt;,&amp;nbsp; המורכב מקהילה של מפתחים עם ידע נרחב ונכונות רבה לעזור.&lt;/p&gt;
&lt;p&gt;ערן.&lt;/p&gt;&lt;/div&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;
&lt;h2&gt;קישורים חיצוניים&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="DIRECTION:ltr;"&gt;Threading in C#&lt;/span&gt; – מאמרים מעשיים 
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.albahari.com/threading/default.aspx#_Introduction" target="_blank"&gt;לחץ לקריאה&lt;/a&gt; (אנגלית) – מאמר מעשי ומקיף. מאמר זה מכיל בנוסף מידע על כלים שאפשרים פיתוח אפליקציות שיעבדו בצורה מקבילית – מומלץ. &lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.yoda.arachsys.com/csharp/threads/" target="_blank"&gt;לחץ לקריאה&lt;/a&gt; (אנגלית) – מאמר מעשי&amp;nbsp; ומקיף. &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Interlocked 
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.interlocked.aspx" target="_blank"&gt;לחץ לקריאה&lt;/a&gt; (אנגלית) – תיעוד בMSDN &lt;/li&gt;
&lt;li&gt;&lt;a href="http://thith.blogspot.com/2005/11/c-interlocked.html" target="_blank"&gt;לחץ לקריאה&lt;/a&gt; (אנגלית) – פוסט קצר ומקצועי המרחיב על נחיצות הinterlocked. &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Singleton 
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://devhood.com/tutorials/tutorial_details.aspx?tutorial_id=486" target="_blank"&gt;לחץ לקריאה&lt;/a&gt; (אנגלית) – דוגמא נוספת &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style="TEXT-ALIGN:right;DIRECTION:rtl;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=679384" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/Web/default.aspx">Web</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/Threading/default.aspx">Threading</category><category domain="http://blogs.microsoft.co.il/blogs/esakal/archive/tags/asp.net/default.aspx">asp.net</category></item></channel></rss>