tag:blogger.com,1999:blog-8828219503554326992024-03-14T00:40:12.886+11:00Paul BatumJust another software developer trying to improve his craft.Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.comBlogger71125tag:blogger.com,1999:blog-882821950355432699.post-68779673919734303242011-12-14T08:38:00.000+11:002011-12-14T08:40:23.981+11:00Gotcha when installing Windows Azure SDK for Node.js<p>I’m pretty excited about the <a href="https://www.windowsazure.com/en-us/develop/nodejs/">Windows Azure SDK for Node.js</a> which landed this week. However there is one thing to be aware of when installing this SDK if you also do Azure development in Visual Studio. Essentially the problem is that the installer does not update the Visual Studio tools for Azure, and you can end up with bits on your machine that are out of sync. Here’s an example of what can happen:</p> <p>You have a Visual Studio solution with a web application project and you right click and choose “Add Windows Azure Deployment Project”:</p> <p><a href="http://lh4.ggpht.com/-zYXm1Olnn-k/TufGQsb24yI/AAAAAAAAAbA/1tP7Btu6LQM/s1600-h/clip_image002%25255B4%25255D.jpg"><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="clip_image002" border="0" alt="clip_image002" src="http://lh6.ggpht.com/-PWhLTVV5RSU/TufGQ_vXDqI/AAAAAAAAAbE/DVM1iOrJ8m0/clip_image002_thumb%25255B1%25255D.jpg?imgmax=800" width="366" height="47" /></a></p> <p>Visual studio gives you this generic error:</p> <p><strong>Windows Azure Tools for Microsoft Visual Studio</strong></p> <p><strong>The command could not be completed: Exception has been thrown by the target of an invocation.</strong></p> <p><a href="http://lh4.ggpht.com/-XWuChZ7bbgw/TufGRG54zRI/AAAAAAAAAbM/4iYfBWnmwkk/s1600-h/clip_image002%25255B5%25255D%25255B3%25255D.jpg"><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="clip_image002[5]" border="0" alt="clip_image002[5]" src="http://lh5.ggpht.com/-7sTAiO31bNg/TufGRLiBAwI/AAAAAAAAAbU/O76skfzXRSc/clip_image002%25255B5%25255D_thumb%25255B1%25255D.jpg?imgmax=800" width="498" height="203" /></a></p> <p>You might end up with a deployment project anyway, but if you try to package it you get this error:</p> <p><strong>WAT080: Failed to locate the Windows Azure SDK. Please make sure the Windows Azure SDK v1.5 is installed.</strong></p> <p><a href="http://lh4.ggpht.com/-VVVKTLYjk1Q/TufGRRcTTZI/AAAAAAAAAbc/WpQetP5CxjA/s1600-h/clip_image002%25255B7%25255D%25255B3%25255D.jpg"><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="clip_image002[7]" border="0" alt="clip_image002[7]" src="http://lh5.ggpht.com/-K0JUYBo3tQA/TufGRtGvYaI/AAAAAAAAAbk/jXJF08gKnTc/clip_image002%25255B7%25255D_thumb%25255B1%25255D.jpg?imgmax=800" width="629" height="65" /></a></p> <p>Fortunately, the resolution for this is very simple. You just need to download the newest version of the <a href="http://www.microsoft.com/web/gallery/install.aspx?appid=WindowsAzureToolsVS2010">Azure SDK for .NET</a> (at time of writing this is the November 2011 version):</p> <p>This will get all your bits in sync, and you can then deploy both .NET and Node.js apps to Azure without issues.</p> Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com0tag:blogger.com,1999:blog-882821950355432699.post-7655362609812479882011-10-14T09:33:00.000+11:002011-10-14T09:39:43.867+11:00Getting to know System.Net.WebSockets: A simple ASP.NET echo server<p>The WebSockets offering for .NET 4.5 consists of several APIs that vary in granularity and purpose. The new System.Net.WebSockets namespace contains a set of types that are used regardless of whether you are hosting your WebSocket server in ASP.NET or if you are using the low level HttpListener class (WCF uses HttpListener when it needs to handle HTTP traffic in self-hosted mode). The goal of this set of types is to define a shared low-level WebSockets API that ASP.NET, WCF and .NET developers can build on top of. </p> <p>System.Net.WebSockets is not to be confused with the new WinRT WebSocket APIs found in Windows.Networking.Sockets. The WinRT APIs provide client functionality only while the the System.Net.WebSockets types are designed for server side use.</p> <p>The easiest way to get to know this new API is to look at a simple example. I’ve <a href="http://paulbatum.github.com/WebSocket-Samples/AspNetWebSocketEcho/">implemented</a> a very basic WebSocket echo server in ASP.NET that demonstrates how to accept a WebSocket connection in ASP.NET, obtain an instance of System.Net.WebSockets.WebSocket and then begin send and receive operations using the methods on this type. Keep in mind that we do not expect most developers to use these low level APIs for every day applications – this is what our <a href="http://nuget.org/List/Packages/Microsoft.WebSockets">Microsoft.WebSockets</a> NuGet package is for. Future posts will cover this package in more detail.</p> <p>I’ve annotated the source code for this echo server and made it available in HTML format. <a href="http://paulbatum.github.com/WebSocket-Samples/AspNetWebSocketEcho/">Please check it out</a>! Do you like samples presented in this style? Let me know in the comments.</p> <p>If you want to download and run this example, it’s called AspNetWebSocketEcho and is part of my <a href="https://github.com/paulbatum/WebSocket-Samples">WebSocket Samples</a> project on github. You will need to use the Windows 8 developer preview if you want to try this stuff out. See my <a href="http://www.paulbatum.com/2011/09/getting-started-with-websockets-in.html">earlier post</a> for instructions on how to set up your development environment. </p> Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com36tag:blogger.com,1999:blog-882821950355432699.post-91917665721929635712011-09-24T10:27:00.001+10:002012-03-12T12:09:16.562+11:00Getting started with WebSockets in Windows 8<p><em>Update: Originally this post was written for the Windows 8 Developer Preview but most of the material is applicable for the Consumer Preview as well. </em><em>My </em><a href="https://github.com/paulbatum/WebSocket-Samples"><em>WebSocket samples project</em></a><em> has been updated to be compatible with the Windows 8 Consumer Preview, so use this instead of the BUILD 2011 samples. </em></p> <p>Last week I <a href="http://channel9.msdn.com/Events/BUILD/BUILD2011/SAC-807T">spoke</a> at the BUILD conference about WebSockets. If you don’t have time to watch the talk, let me try to get you up to speed. The Windows 8 developer preview includes WebSockets support for:</p> <ul> <li>IE 10 </li> <li>The new Windows Runtime </li> <li>IIS 8.0 </li> <li>.NET 4.5 <ul> <li>ASP.NET </li> <li>WCF </li> <li>HttpListener </li> </ul> </li> </ul> <p>During the talk Stefan and I did some demos with ASP.NET and WCF. The purpose of this post is to provide links to the source code for these demos and help you get them up and running in the Windows 8 developer preview. </p> <p>The source code for these demos is now up on github:</p> <p><a href="https://github.com/paulbatum/BUILD-2011-WebSocket-Chat-Samples"><strike>https://github.com/paulbatum/BUILD-2011-WebSocket-Chat-Samples</strike></a> (note: this sample has not been updated for the Windows 8 Consumer Preview) <br /><a title="https://github.com/paulbatum/PushFrenzy" href="https://github.com/paulbatum/PushFrenzy">https://github.com/paulbatum/PushFrenzy</a></p> <p>(If you’re not familiar with git and just want to download the source in a zip, just click the Downloads button on the github pages.)</p> <h4>Setting up the environment</h4> <p>Lets start from the beginning by grabbing a developer preview machine. For this tutorial I’ll be using the Windows Server developer preview which is available on MSDN for subscribers:</p> <p>Operating Systems –> Windows Server Developer Preview –></p> <p><a href="http://lh4.ggpht.com/-tAIKBiDzcFU/Tn0jjuZoa_I/AAAAAAAAAYM/xZ_lAPCrQoM/s1600-h/image%25255B3%25255D.png"><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://lh6.ggpht.com/-DReYGn_rGTc/Tn0jkKEUQtI/AAAAAAAAAYQ/UN-m-B9SoAA/image_thumb%25255B1%25255D.png?imgmax=800" width="704" height="60" /></a></p> <p>I’m using the server SKU because IIS is limited to 10 connections in the client SKU. <strong>However if you are not an MSDN subscriber you can still follow along by downloading the developer preview with developer tools at the </strong><a href="http://msdn.microsoft.com/en-us/windows/apps/br229516"><strong>Windows dev center</strong></a>. <strike>If you do this you can skip this next step where I install Visual Studio.</strike></p> <p><em>Update: The version of Visual Studio that comes pre-installed with the Windows developer preview is an express SKU and will not run these demos. Follow the instructions below to make sure you install the full version of the Visual Studio 11 developer preview.</em></p> <p>Once the Windows 8 is up and running in Hyper-V I run the Visual Studio 11 developer preview installer. There are two ways to do this. Option one is to use the ISO that is available to MSDN subscribers:</p> <p>Developer Tools –> Visual Studio 11 Developer Preview –></p> <p><a href="http://lh4.ggpht.com/-jJENGQJT51I/Tn0jkc15jmI/AAAAAAAAAYU/U53yII5ASPI/s1600-h/image%25255B16%25255D.png"><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://lh3.ggpht.com/-NxuygG2LL-8/Tn0jrloLwzI/AAAAAAAAAYY/knwKVPKnqkQ/image_thumb%25255B6%25255D.png?imgmax=800" width="673" height="44" /></a></p> <p>Option two: Use the public installer available here: <br /><a href="http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=27543">http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=27543</a></p> <p>After installing Visual Studio I enable IIS, the WebSocket module and HTTP activation for WCF to allow WCF to accept WebSockets connections. I add the Web Server role:</p> <p><a href="http://lh6.ggpht.com/-KYNLhHfstPs/Tn0jr8VJrmI/AAAAAAAAAYc/5en2_o2ME3g/s1600-h/image%25255B115%25255D.png"><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://lh5.ggpht.com/-9ardbym3NQ4/Tn0jscKWl2I/AAAAAAAAAYg/mVsE7lsuH7A/image_thumb%25255B57%25255D.png?imgmax=800" width="404" height="309" /></a></p> <p>I enable ASP.NET 4.5 and HTTP Activation:</p> <p><a href="http://lh4.ggpht.com/-chXtqWy5pF4/Tn0jtIgmwwI/AAAAAAAAAYk/tDS04mEIPEE/s1600-h/image%25255B32%25255D.png"><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://lh4.ggpht.com/-KoWrTb1CRgg/Tn0jtQedHEI/AAAAAAAAAYo/HrgEv2kgvUM/image_thumb%25255B14%25255D.png?imgmax=800" width="498" height="131" /></a></p> <p>And I enable WebSockets for IIS:</p> <p><a href="http://lh5.ggpht.com/-rIVa-z9S_VM/Tn0jtiS9oAI/AAAAAAAAAYs/8TOlSfiebhY/s1600-h/image%25255B40%25255D.png"><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://lh6.ggpht.com/-4atws0fkMPg/Tn0juChInVI/AAAAAAAAAYw/fIfvSc_L5-w/image_thumb%25255B18%25255D.png?imgmax=800" width="387" height="294" /></a></p> <p>The user interface will be different if you are doing this on the client SKU but the options you need to select are basically the same. Let me know in the comments if you are having difficulty.</p> <p>If you are on the server SKU you’ll want to disable IE Enhanced Security Configuration (its on by default):</p> <p><a href="http://lh4.ggpht.com/-L3zYustGpY4/Tn0juebJcuI/AAAAAAAAAY0/h5y3q0va-IQ/s1600-h/image%25255B114%25255D.png"><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://lh3.ggpht.com/-vAzbV904wx8/Tn0jur3PBRI/AAAAAAAAAY4/Y-blJpbk3Xg/image_thumb%25255B56%25255D.png?imgmax=800" width="502" height="253" /></a></p> <p>I’ll be using NuGet so I’ll install that too, using the Extension Manager in Visual Studio:</p> <p><a href="http://lh5.ggpht.com/-mkv6uX2c3sI/Tn0jvCD_MUI/AAAAAAAAAY8/TzgH4gU94CQ/s1600-h/image%25255B113%25255D.png"><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://lh4.ggpht.com/-lrDCe8ZzjCU/Tn0jvhyw_8I/AAAAAAAAAZA/K8msoXQRol4/image_thumb%25255B55%25255D.png?imgmax=800" width="609" height="419" /></a></p> <h4>Opening and compiling the code</h4> <p>The good news is that after doing all that setup work, getting the sample apps up and running should be a piece of cake. One thing to be aware of is that WebSockets won’t run in IIS express at the moment. We’ll be using IIS 8.0, so you are going to be best off with running Visual Studio as an administrator.</p> <p>The simplest sample would be the BasicAspNetChat sample. Open BasicAspNetChat.csproj in Visual Studio:</p> <p><a href="http://lh4.ggpht.com/-OBrIiq7fvzU/Tn0jv69jLKI/AAAAAAAAAZE/rRHVPU2QuoI/s1600-h/image%25255B69%25255D.png"><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://lh5.ggpht.com/-9bnD-MAzoF8/Tn0jwbWubCI/AAAAAAAAAZI/H5AHhzZ1ERw/image_thumb%25255B31%25255D.png?imgmax=800" width="261" height="283" /></a></p> <p><em>Update: IIS express might be on by default and if so this will cause problems. Right click on the project, select properties and go to the Web tab. You then need to untick “Use IIS Express” and save your changes:</em></p> <p><a href="http://lh4.ggpht.com/-eOBHQU5LGn8/TogZ7kZpuHI/AAAAAAAAAaM/mrxZBTfyi4I/s1600-h/image%25255B4%25255D.png"><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://lh4.ggpht.com/-pWxKVmP-JUI/TogZ78UMceI/AAAAAAAAAaQ/IknRv27PiKQ/image_thumb%25255B2%25255D.png?imgmax=800" width="665" height="353" /></a></p> <p>If you’re running VS as an administrator your virtual directory should already be created and all you have to do is hit F5. IE 10 should load up and you’ll be prompted to enter a name:</p> <p><a href="http://lh6.ggpht.com/-GTqVklBAb0o/Tn0jwklScRI/AAAAAAAAAZM/90dQcHPltLQ/s1600-h/image%25255B73%25255D.png"><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://lh6.ggpht.com/-5qXOqt6-WK8/Tn0jxFqwDPI/AAAAAAAAAZQ/DPcO3S0TgvI/image_thumb%25255B33%25255D.png?imgmax=800" width="596" height="191" /></a></p> <p>Click the ‘Join chat’ button. This will establish the WebSocket connection. You can then chat with yourself by typing a message into the textbox and clicking ‘Broadcast Message’:</p> <p><a href="http://lh5.ggpht.com/-SFSaEX2SQ-0/Tn0jxSoqG-I/AAAAAAAAAZU/DWo2WBDiHNA/s1600-h/image%25255B83%25255D.png"><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://lh5.ggpht.com/-3Hn2-70Z4LQ/Tn0jx26IfJI/AAAAAAAAAZY/s8hGuxE01xc/image_thumb%25255B37%25255D.png?imgmax=800" width="518" height="239" /></a></p> <p>If you want to try out browser interoperability, download Google Chrome and give it a go. At time of writing, the stable build of Chrome is version 14, and this supports the same version of WebSockets as the Windows 8 developer preview. Just open up Chrome and browse to the same page and follow the same steps:</p> <p><a href="http://lh5.ggpht.com/-L3S4PtT47TA/Tn0jyKoDCsI/AAAAAAAAAZc/1ok5atkAMkM/s1600-h/image%25255B84%25255D.png"><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://lh5.ggpht.com/-b7FH7moUFqw/Tn0jykQRoXI/AAAAAAAAAZg/1slPYthoVQA/image_thumb%25255B38%25255D.png?imgmax=800" width="820" height="291" /></a></p> <p>Curious about what is going on under the hood? Lets hit F12 in Chrome and then rejoin the chat:</p> <p><a href="http://lh6.ggpht.com/-QMCCzBDt7p0/Tn0jy4kRMaI/AAAAAAAAAZk/m5B-6ak0e74/s1600-h/image%25255B92%25255D.png"><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://lh4.ggpht.com/-VwBADyzupv8/Tn0jzWb55dI/AAAAAAAAAZo/et8D9xo7HIU/image_thumb%25255B42%25255D.png?imgmax=800" width="489" height="59" /></a></p> <p>Expand the headers on this and you can see the WebSocket handshake in action:</p> <p><a href="http://lh3.ggpht.com/-4dF7EuE1QrM/Tn0jzlX3BiI/AAAAAAAAAZs/1FtZAUW-8D0/s1600-h/image%25255B88%25255D.png"><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://lh4.ggpht.com/-DH-fFjvQ0kU/Tn0jz2ArJeI/AAAAAAAAAZw/ZvRGDhp-y9M/image_thumb%25255B40%25255D.png?imgmax=800" width="476" height="292" /></a></p> <p>You should find the SignalRChat sample is easy to open and run. This sample is taking advantage of <a href="https://github.com/SignalR/SignalR">SignalR</a>, which is an awesome open source project from my coworkers <a href="http://damianedwards.wordpress.com/">Damian Edwards</a> and <a href="http://weblogs.asp.net/davidfowler/default.aspx">David Fowler</a>. SignalR is basically <a href="http://socket.io/">Socket.IO</a> for ASP.NET – it abstracts the underlying communication mechanism (long polling, websockets, etc) and it lets you do RPC style programming from JavaScript. The SignalR sample works the same as the basic chat sample described above, but the implementation makes use of SignalR rather than WebSockets directly.</p> <p>The last sample I’ll mention today is my little game, Push Frenzy. When you open and run the project (make sure PushFrenzy.Web is the startup project), you should get this screen in IE 10:</p> <p><a href="http://lh6.ggpht.com/-n21_P0y_KNw/Tn0j0Whb1rI/AAAAAAAAAZ0/y9XxNVBFEQc/s1600-h/image%25255B112%25255D.png"><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://lh6.ggpht.com/-Mfw9_Gn7Z5U/Tn0j0wZlwBI/AAAAAAAAAZ4/frFd3M7VZqs/image_thumb%25255B54%25255D.png?imgmax=800" width="399" height="274" /></a></p> <p>To just test that it works, go ahead and enter your name, pick Solitaire mode and then click Play. You should see the game load up (it might take a few seconds on first run):</p> <p><a href="http://lh4.ggpht.com/-W-fromcMwg4/Tn0j1YLxhlI/AAAAAAAAAZ8/YzhXoMLm5Jw/s1600-h/image%25255B111%25255D.png"><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://lh5.ggpht.com/-CeZj_1F-mFE/Tn0j16OQDyI/AAAAAAAAAaA/tm2-1rWxlHM/image_thumb%25255B53%25255D.png?imgmax=800" width="434" height="349" /></a></p> <p>Just refresh the page to join a new game. Open two windows/tabs and have them both join a two player game. You should see that each player’s moves are instantly communicated to each other thanks to the power of WebSockets!</p> <p><a href="http://lh3.ggpht.com/--EPsQ8rIPjk/Tn0j2XL4mxI/AAAAAAAAAaE/rYr3K5NNwpk/s1600-h/image%25255B110%25255D.png"><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://lh6.ggpht.com/-Xa67RG5wxck/Tn0j2sXikjI/AAAAAAAAAaI/IWnOC6UbmG8/image_thumb%25255B52%25255D.png?imgmax=800" width="740" height="328" /></a></p> <p>That’s it for today. Please let me know in the comments if you had any problems following these instructions. In future posts I’ll be diving into the APIs and looking at coding with WebSockets in more detail!</p> Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com56tag:blogger.com,1999:blog-882821950355432699.post-62241203983505579272011-06-05T12:55:00.001+10:002011-06-05T13:05:37.331+10:00WebSockets @ Portland Code Camp 2011<p>Today I spoke at Portland Code Camp 2011 about WebSockets. </p> <p>The code for the “perfmon in your browser” demo I wrote during the session is here: <br /><a href="https://github.com/paulbatum/WebSocketSmoothieDemo">https://github.com/paulbatum/WebSocketSmoothieDemo</a> </p> <p><a href="http://lh6.ggpht.com/-ipdVjmQ0oac/Teryfa_ezJI/AAAAAAAAAXE/2iAWrqL-hPU/s1600-h/image%25255B9%25255D.png"><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://lh5.ggpht.com/--rCQoDHDHKc/TerygGECVsI/AAAAAAAAAXI/82ItxiCUBxw/image_thumb%25255B5%25255D.png?imgmax=800" width="571" height="292" /></a></p> <p>I based my session around the HTML5 Labs WebSockets prototype which is here: <br /><a href="http://html5labs.interoperabilitybridges.com/prototypes/websockets/websockets/info">http://html5labs.interoperabilitybridges.com/prototypes/websockets/websockets/info</a></p> <p>You will need to install the MSI available at the above link and then reference the dll’s that it installs as I do not have permission to redistribute the dll’s myself.</p> <p>I used a particular Aurora build of Firefox that supports version 07 of the WebSocket protocol: <br /><a title="http://www.ducksong.com/misc/websockets-builds/ws-07/5.0.a2.04/" href="http://www.ducksong.com/misc/websockets-builds/ws-07/5.0.a2.04/">http://www.ducksong.com/misc/websockets-builds/ws-07/5.0.a2.04/</a></p> <p>Thankfully I was able to fix all of my mistakes quite quickly so I did not have to use the 1.8 release of Firebug that I typically debug with in Aurora: <br /><a title="http://getfirebug.com/releases/firebug/1.8/" href="http://getfirebug.com/releases/firebug/1.8/">http://getfirebug.com/releases/firebug/1.8/</a></p> <p>I used several NuGet packages (jQuery, JsonValue, json2).</p> <p>I used Smoothie to do the canvas graph (if you grab the version included with my code you are getting my modified version): <br /><a title="http://smoothiecharts.org/" href="http://smoothiecharts.org/">http://smoothiecharts.org/</a></p> <p>If you have any questions or feedback on the talk drop me a line on email, twitter, or leave a comment here on my blog.</p> <p>Thanks for your interest in WebSockets!</p> Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com0tag:blogger.com,1999:blog-882821950355432699.post-81024162441833998742011-04-25T06:49:00.002+10:002011-05-23T07:29:09.326+10:00WebSockets MIX 11 Demo<p><b>Update</b>: HTML5 labs has released a new version of the prototype based on version 07 of the WebSocket protocol. I've updated my demo to use this version, and I've tested successfully against a nightly build of firefox that also supports 07 (see link below).</p><p>I've had some requests for the source code for the tiny WebSockets demo I did at MIX. I’ve put the code up on github:
<a href="https://github.com/paulbatum/WebSockets-MIX11-Demo">https://github.com/paulbatum/WebSockets-MIX11-Demo</a></p> <p>(You don’t need to use git to grab this, just click the download link.)</p> <p>I don’t have a license to redistribute the two binaries that I reference:
<strong>Microsoft.ServiceModel.Tcp.dll
Microsoft.ServiceModel.WebSockets.dll</strong></p> <p>But these are included in the HTML5 Labs WebSocket prototype, which is here:
<a href="http://html5labs.interoperabilitybridges.com/html5labs/prototypes/websockets/websockets/download/">http://html5labs.interoperabilitybridges.com/html5labs/prototypes/websockets/websockets/download/</a></p> <p>Once the install is complete, you'll have the prototype bits at:
<strong>C:\Program Files (x86)\Microsoft SDKs\WCF WebSockets</strong> or
<strong>C:\Program Files\Microsoft SDKs\WCF WebSockets</strong> if you are on a 32-bit OS.</p> <p>If you are going to use the Silverlight plugin to simulate WebSockets, you'll need to drop the clientaccesspolicy.xml file (found in the bin folder) into your <strong>c:\inetpub\wwwroot</strong> folder.</p> <p>If you want to use the private build of Firefox with support for 07 WebSockets, you can get this here:
<a href="http://www.ducksong.com/misc/websockets-builds/ws-07/5.0.a2.03/">http://www.ducksong.com/misc/websockets-builds/ws-07/</a></p> <p>Finally, you can follow along with the MIX video:
<a href="http://channel9.msdn.com/events/MIX/MIX11/HTM10">http://channel9.msdn.com/events/MIX/MIX11/HTM10</a></p>Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com1tag:blogger.com,1999:blog-882821950355432699.post-74175286203435555312011-04-14T11:23:00.002+10:002011-04-14T11:33:01.718+10:00My MIX video is upMy talk is <a href="http://channel9.msdn.com/Events/MIX/MIX11/HTM10">here</a>. It went reasonably smoothly - to be honest I'm just glad that the demo worked fine and I didn't manage to say anything insanely stupid.<div>
</div><div>There's lots of interesting talks online now, with more to come. Check em out:</div><div><a href="http://live.visitmix.com/mix11">http://live.visitmix.com/mix11</a>
</div>Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com0tag:blogger.com,1999:blog-882821950355432699.post-41525105800692612182011-04-10T11:25:00.001+10:002011-04-10T11:25:37.074+10:00MIX 2011<p>I’m <a href="http://channel9.msdn.com/events/MIX/MIX11/HTM10">speaking</a> at MIX this year! Craig Kitterman and I will be talking about WebSockets and taking a look at the prototype available on <a href="http://html5labs.interoperabilitybridges.com/">HTML5 Labs</a>. If you are interested in WebSockets and prefer to develop on Windows, I definitely recommend you check out the prototype. It is WCF based but trust me you don’t have to write a line of XML, and its very simple to get a WebSocket server up and running. </p> <p>MIX sessions are recorded so if you can’t make it to MIX don’t worry, all my stuff-ups will be caught on video and preserved for your amusement. I’ll post an update when the video is online.</p> Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com0tag:blogger.com,1999:blog-882821950355432699.post-56713174551750850872011-02-14T16:17:00.002+11:002011-02-24T11:42:03.089+11:00One Month at Microsoft<p>Late last year I accepted a job offer from Microsoft, got married and moved to the US. Its been a busy few months! I’m based in Redmond, working in the WCF team as a program manager. I started early January, so I’ve been working for just over a month now and thought it might be worth doing a post on my thoughts on Microsoft so far.</p> <p>Working at Microsoft is quite an experience. It’s been a change at many levels for me. For example, moving from a small company to a ridiculously big one requires an adjustment in its own right. There are so many people, so many projects with subtle interactions between them. And lets face it - a large company can’t help but breed its own unique flavor of internal politics and an insane number of meetings. I’d have to say that in most ways, the experience has met my expectations. Though I was surprised that it was several days before I had a PC and a working network login – I expected a large company to have that stuff down cold. Were my expectations just completely backwards on this one? Let me know in the comments :)</p> <p>The move from dev lead to program manager is also a significant change – my productivity suite is Office now, not Visual Studio (hopefully it will get closer to 50 / 50 in time). In essence, program management is about determining what to build, what the user experience is like, planning and overseeing the execution and then letting customers know about the awesome thing your team built. I don’t think I could be a program manager on Office, or Windows or some other product that isn’t developer focused. At least this way when I’m prototyping or refining the user experience or preparing demos I’m working with code. But I still wonder if program management is the best fit for me. Its way too early to tell at this point so I’ll just have to wait and see. If you would like to learn more about program management I suggest you read Steven Sinofsky’s epic, awesome <a href="http://blogs.msdn.com/b/techtalk/archive/2005/12/16/504872.aspx">post</a>. </p> <p>For my first month at Microsoft, there was stark contrast between the first two weeks and the following two. During the first two weeks, a significant portion of my time was spent on “administrivia”: permissions, online training, getting yourself included in the right meetings, filling out forms, etc. At the end of my second week I began to wonder when the “work” was really going to begin – and then it promptly did! I felt very busy and quite overwhelmed for the next two weeks as my responsibilities began to crystalize. This last week felt somewhat more manageable but I have a feeling this won’t last long as various deadlines loom towards the end of the month.</p> <p>I’d heard that they really liked their TLA’s at Microsoft, but I imagined that it was blown out of proportion. Sure technical people like their acronyms – hell, ask me about programming and I’ll probably start spouting stuff about DDD, TDD, BDD, CQRS, IOC, etc. After spending a month at Microsoft I have to say that their reputation for acronym overuse is well deserved. Its funny, they even change the names of stuff to avoid unpleasant acronyms. Case in point – Microsoft is divided into divisions, but the “Server and Tools” division is actually referred to as a “business”. How amusing.</p> <p>Putting aside the quirks, the last month has been exciting, challenging and tremendously educational. Its fantastic to get a chance to learn how things work on the inside of the company that I’ve built my career around. I have been consistently impressed with the intelligence and approachability of my coworkers and it is in this aspect that I really feel like the promise of Microsoft has delivered. I wanted to find an environment where I felt challenged by the people around me to learn and grow and I can safely say I’ve found one.</p>Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com4tag:blogger.com,1999:blog-882821950355432699.post-45553121676374051612010-08-01T18:07:00.000+10:002010-08-01T18:10:26.738+10:00My Technology Stack<p>A bunch of <a href="http://ang3lfir3.wordpress.com/2010/07/30/my-technology-stack/">people</a> have been <a href="http://hackingon.net/post/My-Technology-Stack.aspx">posting</a> <a href="http://wolfbyte-net.blogspot.com/2010/07/my-magic-unicorns-technology-stack.html">answers</a> to David Burela’s ‘<a href="http://davidburela.wordpress.com/2010/07/30/developer-blog-banter-1-what-is-your-preferred-technology-stack/">What is your preferred technology stack?</a>’ question and I thought I’d join in. At work we’re just finishing up on a smallish project that uses this stack:</p> <ul> <li><strong>ASP.NET MVC 2.0 <br /></strong>If you’re developing web applications on Microsoft’s stack, the Web Forms vs MVC decision will have the most significant effect on your day to day development experience. I find Web Forms to be a harmful, leaky abstraction and cannot get enough of MVC’s simplicity, especially when it comes to AJAX development. </li> <li><strong>MVC Contrib <br /></strong>Fills in some of ASP.NET MVC’s gaps. </li> <li><strong>jQuery <br /></strong>Just don’t do JavaScript without it. </li> <li><strong>jQuery.UI</strong>, <strong>jQuery.Validate, jQuery.Form, <strong>jqGrid <br /></strong></strong>I use a few other jQuery plugins but these are the most useful ones. </li> <li><strong>NHibernate + Fluent NHibernate + NHibernate.Validator <br /></strong>This should hardly come as a surprise, given that I’m a member of the Fluent NHibernate team. We’re using a trunk build of NHibernate 3.0 which includes the work on the new LINQ provider. In terms of Fluent NHibernate usage, we go the automapping route as our domain models are pretty straightforward. We sacrifice domain “purity” and use NHibernate.Validator’s attributes because they are just so damn convenient. I’d be quite comfortable with making a move to the fluent interface though. </li> <li><strong>Castle Windsor <br /></strong>When it comes to IoC containers, I don’t have particularly strong feelings. I’ve used Structure Map a bit and I prefer it to Windsor but its easy to go with Windsor because Sharp Architecture includes it. My next home project that needs a container will use AutoFac as I’ve been meaning to try it. </li> <li><strong>Sharp Architecture <br /></strong>Glue for ASP.NET MVC, Fluent NHibernate, Castle.Windsor and other projects. Sharp Architecture gives you a bunch of handy stuff and from a rapid development perspective its quite nice to drop in. But I’m not entirely comfortable with some of the assumptions it makes. For larger projects, I’ll reuse a bunch of the code from Sharp Architecture, rather than referencing it as a binary. </li> <li><strong>xVal <br /></strong>Acts as a bridge between NHibernate.Validator and jQuery.Validate. This way we stick [NotEmpty] style attributes on our domain model and we get client side validation for free. I’m aware that ASP.NET MVC 2.0 includes some xVal style functionality but I wasn’t able to figure out if there was a better option so I just stuck with xVal since it worked so nice on my last MVC (1.0) project. </li> <li><strong>Elmah <br /></strong>Drop it into your solution in 10 minutes and then forget about exception logging. </li> <li><strong>NUnit <br /></strong>I’d like to try some other unit testing frameworks but its hard to find the time. NUnit works well enough for now. </li> <li><strong>Microsoft Team Foundation Server <br /></strong>Ugh. We use it for source control, builds, and work tracking – and its my fault! (a mistake from many years ago, sigh). I wish we were using git. </li> </ul> <p>The only problem with a stack like this is that when you decide to use a newer NHibernate build, you’ve got a whole bunch of projects to recompile. I’m still waiting for some clever folks to sort this problem out :)</p> Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com2tag:blogger.com,1999:blog-882821950355432699.post-20265074268035772422010-03-12T20:11:00.001+11:002010-03-12T20:11:21.853+11:00Talking Shop<p>Last week I was <a href="http://www.talkingshopdownunder.com/2010/03/talking-shop-down-under-podcast-episode.html">featured</a> on the <a href="http://www.talkingshopdownunder.com/">Talking Shop Down Under</a> podcast. Fellow aussie Richard Banks was kind enough to extend me an invitation a few weeks back to join him on his show but I told him there were “… many more interesting aussies to interview before we get to me” and suggested he start with <a href="http://www.albahari.com/">Joe Albahari</a> (LINQPad rocks!!). Boy I knew I was in trouble when the very next podcast rolled through featuring Joe – Richard sure doesn’t waste any time!</p> <p>In the podcast we discuss Fluent NHibernate, git, and my reasons for doing open source. For those of you that were hoping for some more Reactive Extensions content, I’m afraid I’ve been neglecting Rx lately so I didn’t feel qualified to talk much about it. Maybe next time?</p> <p>Thanks to Richard for having me on the show, it was lots of fun. If you do have a listen, please feel free to leave a comment – this was my first podcast and I haven’t done a great deal of public speaking so I could benefit from some constructive criticism. Cheers!</p> Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com0tag:blogger.com,1999:blog-882821950355432699.post-9165670336476583232010-02-07T23:01:00.000+11:002010-02-07T23:02:21.762+11:00Advanced Distributed Systems Design with Udi Dahan<p>I spent last week in Melbourne for a 5 day training course on distributed systems, run by <a href="http://www.udidahan.com/">Udi Dahan</a>. I’ve been a fan of Udi’s work for a while now, so when I discovered that he was on his way to Australia I jumped at the chance to be immersed in his approach to designing scalable and reliable distributed systems. Let me tell you – I was not disappointed. I found Udi’s course to be very challenging – not in terms of difficulty, but rather that it was full of ideas that challenged my <em>preconceptions</em>. I was also very impressed with Udi’s presentation and communication skills. He really knows the material and has an amazing ability to give helpful, informative answers to really dumb questions :)</p> <p>The course was focused on a few key ideas:</p> <ul> <li>Service oriented architecture </li> <li>Message based systems </li> <li>Command / query responsibility segregation </li> <li>Domain models </li> </ul> <p>If you’d like a more detailed breakdown of the course content, Udi has provided an <a href="http://www.udidahan.com/training/">overview</a> on his website. </p> <p>I’ve tried to understand SOA before and struggled with the abstractness of the concept. I guess part of my difficulty has always come from the fact that I still approach the world with a “developer” mindset – I’ve never really bought into the concept of a non-coding architect and sometimes I struggle to understand the meaning and implications of an idea if I can’t see the actual effect on the code we write. </p> <p>Thanks to Udi, I now have a basic understanding of what SOA means. I am comfortable with the idea of identifying <em>business capabilities</em> and describing them as services that consist of business components, which in turn consist of autonomous components that are individually deployable. I’m also comfortable with the idea of these autonomous components communicating with each other via a message bus using a combination of asynchronous request-reply and publish-subscribe. I am not yet sure how well my understanding will map to the existing literature on SOA, as I got the impression from some of the other students that Udi’s version of SOA was somewhat different to the SOA they had read about. My impression of SOA is that it is a slippery subject, where only the most abstract and vague definitions are widely accepted. That said, I can see a great deal of value in the analytical process and technical approach that Udi taught us.</p> <p>Having skimmed <a href="http://www.eaipatterns.com/">Enterprise Integration Patterns</a>, I was already familiar with the idea of message based systems and the advantages of temporal decoupling before I began the course. But Udi’s coverage of the topic helped fill in large gaps and also gave me a great deal of appreciation for the power and simplicity of his open source .NET based service bus, <a href="http://www.nservicebus.com">NServiceBus</a>. My co-worker Malcolm nearly did a backflip when he saw how easy it is to begin using NServiceBus alongside WCF.</p> <p>Command / query responsibility segregation (CQRS) is about recognising the difference between queries and commands as part of system architecture, and designing completely different paths for handling the two types of operations. Going into the course, I thought I was comfortable with the idea as I’d watched a number of videos on the topic from <a href="http://codebetter.com/blogs/gregyoung/">Greg Young</a>, and had read a number of blog posts. It turned out that Udi had his own take on CQRS that I did not pick up on when reading his posts on the topic. Speaking of Udi’s posts on the topic of CQRS, I highly recommend <a href="http://www.udidahan.com/2009/12/09/clarified-cqrs/">this one</a> if you’d like to learn more.</p> <p>So how was Udi’s version of CQRS different to what I expected? One example immediately comes to mind. A necessary part of CQRS is some sort of persistent view model to facilitate the queries, and a transactional data model to facilitate the commands. So far, so good. Udi then introduced the idea that there may be some relationships that are only recorded in the persistent view model, and not in the transactional model – if later on you need that data in your transactional store, then backfill it with an ETL from your view model! Boy did that raise some incredulous looks, especially from yours truly! “What happened to my single source of truth?” I cried.</p> <p>Udi also had some interesting ideas about domain models. In particular, we went into quite a bit of detail on the idea of aggregates, and how to ensure consistency. Has it ever occurred to you that perhaps there is something wrong with loading a Customer, and then lazily loading their Orders at some later point? What happens if one of the Orders are modified by another process, after the Customer is loaded but before the Orders are lazily loaded? Now the model loaded into memory is inconsistent! Even if your optimistic concurrency will protect you in most of these scenarios, its entirely possible that you’re updating some other object based on logic that has operated on your inconsistent snapshot. This problem seemed obvious once it was pointed out, but it had never occurred to me before.</p> <p>There were so many interesting discussions and points of contention over the 5 days, this post has barely begun to skim the surface. It really was an eye opening experience for me, and some serious food for thought. If you ever get the opportunity to attend Udi’s course, don’t hesitate. Its worth it!</p> <p>Now that I’ve finally managed to get something written down on the course, I’ll let myself read some of the summaries written <a href="http://www.markharris.net.au/blog/2010/02/04/doing-advanced-distributed-systems-design-a-gift-from-santa">by</a> <a href="http://rhysc.blogspot.com/2010/01/udi-dahan-advanced-distributed-systems.html">other</a> <a href="http://www.simonsegal.net/blog/2010/02/04/adsd-nservicebus-and-nuclear-armament-the-full-story/">attendees</a>.</p> Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com0tag:blogger.com,1999:blog-882821950355432699.post-73069043033024409862009-11-18T22:00:00.001+11:002009-11-18T22:00:19.346+11:00Reacting to the Reactive Framework: Part 8<p>Today I caught wind of some news that was bound to rouse me from my blogging slumber. The Reactive Framework, now known as Reactive Extensions (or Rx for short) has been <a href="http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx">released</a> on DevLabs. The good news is that this release includes versions for .NET 3.5, .NET 4 Beta 2 and Silverlight 3, and documentation. The bad news is that at this stage, the documentation is pretty sparse - single sentence summaries and zero examples. Certainly, the summaries will help developer make sense of the impressive range of extension methods available on IObservable. For example, the comment on the rather cryptically named <strong>Amb</strong> - <em>Returns the observable sequence that reacts first - </em>makes its purpose quite clear, even if it doesn’t help explain the name. However the same cannot be said for all the cases, such as <strong>Dematerialize - </strong><em>Dematerializes the explicit notification values of an observable sequence as implicit notifications</em>. Perhaps that will make sense once I understand the difference between explicit and implicit notifications, but its unlikely that the documentation (in its current form) will help me understand this. No matter - this intermediate release is certainly welcome and I now look forward to diving back in to Rx with at least some clue of what things are supposed to do :) </p> <p>If you are interested in the Reactive Extensions I recommend you check out the <a href="http://blogs.msdn.com/RxTeam/">team blog</a>. The <a href="http://blogs.msdn.com/rxteam/archive/2009/11/17/announcing-reactive-extensions-rx-for-net-silverlight.aspx">announcement post</a> has plenty of links for you to click and learn more. I also recommend Matt Podwysocki’s <a href="http://codebetter.com/blogs/matthew.podwysocki/archive/2009/10/14/introducing-the-reactive-framework-part-i.aspx">series</a> <a href="http://codebetter.com/blogs/matthew.podwysocki/archive/2009/11/03/introduction-to-the-reactive-framework-part-ii.aspx">of</a> <a href="http://codebetter.com/blogs/matthew.podwysocki/archive/2009/11/12/introduction-to-the-reactive-framework-part-iii.aspx">Rx</a> <a href="http://codebetter.com/blogs/matthew.podwysocki/archive/2009/11/15/introduction-to-the-reactive-framework-part-iv.aspx">posts</a>. Also, don’t forget that now Rx is on DevLabs, there’s a dedicated <a href="http://social.msdn.microsoft.com/Forums/en-US/rx/threads">forum</a>.</p> Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com2tag:blogger.com,1999:blog-882821950355432699.post-7502761893810037752009-08-11T17:55:00.000+10:002010-07-25T16:02:03.392+10:00Reacting to the Reactive Framework: Part 7<p>The demo application for today allows the user to experiment with a couple of the mechanisms that I tried for <a href="http://www.paulbatum.com/2009/08/reacting-to-reactive-framework-part-6.html">part 6</a>. As you may recall, I wanted an IObservable<int[]> that would return the three selections made from three groups of radio buttons, and only begin returning values once a selection had been made from all three. The demo app allows you to switch between using SelectMany, ForkJoin and CombineLatest and observe how the behavior changes:</p> <iframe style="width: 500px; height: 350px" src="http://paulbatumco.web709.discountasp.net/combinationex2/SilverlightAppTestPage.html" frameborder="0" scrolling="no"></iframe> <p>The first approach I tried was SelectMany - I’ll use the query comprehension syntax as it is much more readable than calling the SelectMany extension method directly:</p> <pre class="code"><span style="color: blue">from </span>s1 <span style="color: blue">in </span>choiceControl1.OptionSelections
<span style="color: blue">from </span>s2 <span style="color: blue">in </span>choiceControl2.OptionSelections
<span style="color: blue">from </span>s3 <span style="color: blue">in </span>choiceControl3.OptionSelections
<span style="color: blue">select new</span>[] { s1, s2, s3 }</pre>
<p>This syntax might be readable, but its also a little misleading. It looks very uniform, like it wouldn’t matter which order you wrote those three ‘from’ statements in. But if you are familiar with LINQ statements like this one, you will know that the ordering IS important. To observe this, activate the SelectMany option in the app above, and then make your selections in reverse order i.e. select an option from group 3, then group 2, then group 1. Notice how you don’t get a selection readout? What’s actually happening here is that the selections made in groups 2 and 3 are ignored until a selection is made in group 1. Then the selections made in group 3 are ignored, until a selection is made in group 2. Then finally selections from group 3 will trigger the observable and raise a result. I could go into more detail on what’s happening here, but is there much point? Its obvious that this implementation is not at all close to the desired result. Lets move on.</p>
<p>When I came across the signature for ForkJoin, I thought I had found what I was looking for:</p>
<pre>public static <a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Reactive:1.0.0.0:1b331ac6720247d9/System.Collections.Generic.IObservable<>">IObservable</a><<a>TSource</a>[]> <b><a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Reactive:1.0.0.0:1b331ac6720247d9/System.Linq.Observable/ForkJoin<>(System.Collections.Generic.IObservable<<!!0>>%5b%5d):System.Collections.Generic.IObservable<<!!0>%5b%5d>">ForkJoin</a></b><<b>TSource</b>>(params <a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Reactive:1.0.0.0:1b331ac6720247d9/System.Collections.Generic.IObservable<>">IObservable</a><<a>TSource</a>>[] sources); </pre>
<p>It converts many IObservable<T>’s into one IObservable<T[]>, which is exactly what I want. The bad news is that it only works <strong>once</strong>. Go ahead and try ForkJoin in the sample app – the status text will update once a selection has been made from all three groups, but it will not update again as the selection continues to change. It did occur to me that perhaps I could use ForkJoin and somehow re-subscribe each time it fires, but I was reluctant to go down that path because it doesn’t feel like a functional (as in functional programming) solution.</p>
<p>The demo app for today uses CombineLatest in the same way as in my previous post:</p>
<pre class="code">choiceControl1.OptionSelections
.CombineLatest(choiceControl2.OptionSelections, (i, j) => <span style="color: blue">new</span>[] { i, j })
.CombineLatest(choiceControl3.OptionSelections, (array, k) => <span style="color: blue">new</span>[] { array[0], array[1], k }))</pre>
<a href="http://11011.net/software/vspaste"></a>
<p>This works fine, though its not pretty. I’ll keep my eye out for a better solution, but before I finish up today I want to look at the code behind today’s demo app:</p>
<pre class="code"><span style="color: blue"><</span><span style="color: #a31515">StackPanel </span><span style="color: red">Margin</span><span style="color: blue">="20">
<</span><span style="color: #a31515">TextBlock </span><span style="color: red">Text</span><span style="color: blue">="Combining Example" </span><span style="color: red">HorizontalAlignment</span><span style="color: blue">="Center" </span><span style="color: red">Margin</span><span style="color: blue">="10" />
<</span><span style="color: #a31515">StackPanel </span><span style="color: red">Orientation</span><span style="color: blue">="Vertical" </span><span style="color: red">HorizontalAlignment</span><span style="color: blue">="Left">
<</span><span style="color: #a31515">TextBlock </span><span style="color: red">Text</span><span style="color: blue">="Select a means of combination:" />
<</span><span style="color: #a31515">RadioButton </span><span style="color: red">Name</span><span style="color: blue">="rbSelectMany" </span><span style="color: red">Content</span><span style="color: blue">="Use SelectMany" />
<</span><span style="color: #a31515">RadioButton </span><span style="color: red">Name</span><span style="color: blue">="rbForkJoin" </span><span style="color: red">Content</span><span style="color: blue">="Use ForkJoin" />
<</span><span style="color: #a31515">RadioButton </span><span style="color: red">Name</span><span style="color: blue">="rbCombineLatest" </span><span style="color: red">Content</span><span style="color: blue">="Use CombineLatest" />
<</span><span style="color: #a31515">TextBlock </span><span style="color: red">Text</span><span style="color: blue">="Select an option from each group below, and then experiment with changing your selections." </span><span style="color: red">TextWrapping</span><span style="color: blue">="Wrap" </span><span style="color: red">Margin</span><span style="color: blue">="0,10,0,0" />
</</span><span style="color: #a31515">StackPanel</span><span style="color: blue">>
<</span><span style="color: #a31515">StackPanel </span><span style="color: red">Orientation</span><span style="color: blue">="Horizontal" </span><span style="color: red">HorizontalAlignment</span><span style="color: blue">="Center" >
<</span><span style="color: #a31515">SilverlightApp</span><span style="color: blue">:</span><span style="color: #a31515">ChoiceControl </span><span style="color: red">Name</span><span style="color: blue">="choiceControl1" </span><span style="color: red">Heading</span><span style="color: blue">="Group 1"/>
<</span><span style="color: #a31515">SilverlightApp</span><span style="color: blue">:</span><span style="color: #a31515">ChoiceControl </span><span style="color: red">Name</span><span style="color: blue">="choiceControl2" </span><span style="color: red">Heading</span><span style="color: blue">="Group 2"/>
<</span><span style="color: #a31515">SilverlightApp</span><span style="color: blue">:</span><span style="color: #a31515">ChoiceControl </span><span style="color: red">Name</span><span style="color: blue">="choiceControl3" </span><span style="color: red">Heading</span><span style="color: blue">="Group 3"/>
</</span><span style="color: #a31515">StackPanel</span><span style="color: blue">>
<</span><span style="color: #a31515">TextBlock </span><span style="color: red">Name</span><span style="color: blue">="statusText" </span><span style="color: red">Text</span><span style="color: blue">="Status Text" </span><span style="color: red">TextAlignment</span><span style="color: blue">="Center"></</span><span style="color: #a31515">TextBlock</span><span style="color: blue">>
</</span><span style="color: #a31515">StackPanel</span><span style="color: blue">></span></pre>
<a href="http://11011.net/software/vspaste"></a>
<pre class="code"><span style="color: blue">public </span>MainPage()
{
InitializeComponent();
<span style="color: #2b91af">IObservable</span><<span style="color: #2b91af">IObservable</span><<span style="color: blue">int</span>[]>> observerSelections = <span style="color: #2b91af">Observable</span>.Merge(
<span style="color: #2b91af">Observable</span>.FromEvent<<span style="color: #2b91af">RoutedEventArgs</span>>(rbSelectMany, <span style="color: #a31515">"Checked"</span>)
.Select(_ => <span style="color: blue">from </span>s1 <span style="color: blue">in </span>choiceControl1.OptionSelections
<span style="color: blue">from </span>s2 <span style="color: blue">in </span>choiceControl2.OptionSelections
<span style="color: blue">from </span>s3 <span style="color: blue">in </span>choiceControl3.OptionSelections
<span style="color: blue">select new</span>[] { s1, s2, s3 }),
<span style="color: #2b91af">Observable</span>.FromEvent<<span style="color: #2b91af">RoutedEventArgs</span>>(rbForkJoin, <span style="color: #a31515">"Checked"</span>)
.Select(_ => <span style="color: #2b91af">Observable</span>.ForkJoin(choiceControl1.OptionSelections, choiceControl2.OptionSelections, choiceControl3.OptionSelections)),
<span style="color: #2b91af">Observable</span>.FromEvent<<span style="color: #2b91af">RoutedEventArgs</span>>(rbCombineLatest, <span style="color: #a31515">"Checked"</span>)
.Select(_ => choiceControl1.OptionSelections
.CombineLatest(choiceControl2.OptionSelections, (i, j) => <span style="color: blue">new</span>[] { i, j })
.CombineLatest(choiceControl3.OptionSelections, (array, k) => <span style="color: blue">new</span>[] { array[0], array[1], k }))
);
<span style="color: #2b91af">IDisposable </span>subscription = <span style="color: blue">null</span>;
observerSelections.Subscribe(observer =>
{
<span style="color: blue">if </span>(subscription != <span style="color: blue">null</span>)
subscription.Dispose();
choiceControl1.ClearAll();
choiceControl2.ClearAll();
choiceControl3.ClearAll();
statusText.Text = <span style="color: blue">string</span>.Empty;
subscription = observer.Subscribe(UpdateSelectedOptions);
});
}
<span style="color: blue">private void </span>UpdateSelectedOptions(<span style="color: blue">int</span>[] values)
{
statusText.Text = <span style="color: blue">string</span>.Format(<span style="color: #a31515">"Option {0}, Option {1}, Option {2}"</span>,
values[0], values[1], values[2]);
}</pre>
<p>If you recall in the previous post, I was using the Observable.Merge method to glue three separate events together into one observable, and today I’m using the same technique on the radio buttons that let you swap between the different implementations. The difference in this case is that instead of simply returning an integer, I’m returning an IObservable<int[]>, so the result is an IObservable<IObservable<int[]>>. I then subscribe to this so that each time the selected implementation changes, the existing subscription is disposed, the selections are cleared and a new subscription is instated.</p>
<p>What do you think? Am I being too clever for my own good here? Is an IObservable<IObservable<T>> taking it too far? Let me know in the comments!</p>
<p>The code for this post has been <a href="http://github.com/paulbatum/Rx-sandpit/tree/Combination-Ex2">tagged</a> in my github repository.</p> Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com0tag:blogger.com,1999:blog-882821950355432699.post-50656218446091612572009-08-09T02:42:00.000+10:002010-07-25T17:57:06.023+10:00Reacting to the Reactive Framework: Part 6<p>Before I dive into today’s code, there are two things worth mentioning:</p> <ol> <li>If you haven’t already, make haste to <a href="http://themechanicalbride.blogspot.com/">Jafar Husain’s blog</a>. Jafar is posting <a href="http://themechanicalbride.blogspot.com/2009/07/developing-with-rx-part-1-extension.html">truly</a> <a href="http://themechanicalbride.blogspot.com/2009/07/developing-with-rx-part-2-converting.html">interesting</a> <a href="http://themechanicalbride.blogspot.com/2009/08/joy-of-rx-building-asynchronous-service.html">examples</a> of using the Reactive Framework - none of the ‘hello world’ fare I’m peddling here. </li> <li>I mentioned in my previous post that I was having trouble using System.Reactive.dll with non-silverlight projects. Jb Evain has <a href="http://evain.net/blog/articles/2009/07/30/rebasing-system-reactive-to-the-net-clr">the goods</a> on how you might get around this if you were so inclined. For now I’ll stick with Silverlight as its well suited for including interactive demonstrations in my blog posts. </li> </ol> <p>Today I want to look at combining events using the Reactive Framework (Rx). Here is the demo app for today: <em>(Once again I will remind readers using RSS readers to view this post in a proper browser window so you can see the embedded Silverlight app.)</em></p> <iframe style="width: 600px; height: 300px" src="http://paulbatumco.web709.discountasp.net/combinationex1/SilverlightAppTestPage.html" frameborder="0" scrolling="no"></iframe> <p>The idea behind this example is that I am not interested in the selections until an option has been selected from all three groups. From then on, I’d like to be informed whenever the selection changes. This application consists of three instances of a user control, one for each group. Here is the relevant markup and code for the user control:</p> <pre class="code"><span style="color: blue"><</span><span style="color: #a31515">StackPanel </span><span style="color: red">Margin</span><span style="color: blue">="20">
<</span><span style="color: #a31515">TextBlock </span><span style="color: red">Text</span><span style="color: blue">="{</span><span style="color: #a31515">Binding </span><span style="color: red">Heading</span><span style="color: blue">}" </span><span style="color: red">Margin</span><span style="color: blue">="5" />
<</span><span style="color: #a31515">RadioButton </span><span style="color: red">Name</span><span style="color: blue">="optionButton1" </span><span style="color: red">Content</span><span style="color: blue">="Option 1" />
<</span><span style="color: #a31515">RadioButton </span><span style="color: red">Name</span><span style="color: blue">="optionButton2" </span><span style="color: red">Content</span><span style="color: blue">="Option 2" />
<</span><span style="color: #a31515">RadioButton </span><span style="color: red">Name</span><span style="color: blue">="optionButton3" </span><span style="color: red">Content</span><span style="color: blue">="Option 3" />
</</span><span style="color: #a31515">StackPanel</span><span style="color: blue">></span></pre>
<a href="http://11011.net/software/vspaste"></a>
<pre class="code"><span style="color: blue">public </span>ChoiceControl()
{
InitializeComponent();
OptionSelections = <span style="color: #2b91af">Observable</span>.Merge(
<span style="color: #2b91af">Observable</span>.FromEvent<<span style="color: #2b91af">RoutedEventArgs</span>>(optionButton1, <span style="color: #a31515">"Checked"</span>).Select(_ => 1),
<span style="color: #2b91af">Observable</span>.FromEvent<<span style="color: #2b91af">RoutedEventArgs</span>>(optionButton2, <span style="color: #a31515">"Checked"</span>).Select(_ => 2),
<span style="color: #2b91af">Observable</span>.FromEvent<<span style="color: #2b91af">RoutedEventArgs</span>>(optionButton3, <span style="color: #a31515">"Checked"</span>).Select(_ => 3)
);
}
<span style="color: blue">public </span><span style="color: #2b91af">IObservable</span><<span style="color: blue">int</span>> OptionSelections { <span style="color: blue">get</span>; <span style="color: blue">private set</span>; }</pre>
<p><a href="http://11011.net/software/vspaste"></a>As you can see, I am creating IObservables from the Checked events of the radio buttons. I’m using the Select method to make observables that simply return the index, and I’m merging those together into one IObservable<int>. So if the user checked option 1, then option 2, then option 3, the OptionSelections would call OnNext on its subscribed observers with values 1, 2 and 3 respectively. </p>
<p>As I mentioned before, this app has 3 instances of this user control:</p>
<pre class="code"><span style="color: blue"><</span><span style="color: #a31515">StackPanel </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">="LayoutRoot" </span><span style="color: red">Margin</span><span style="color: blue">="50" </span><span style="color: red">Background</span><span style="color: blue">="Azure" </span><span style="color: red">Width</span><span style="color: blue">="400">
<</span><span style="color: #a31515">StackPanel </span><span style="color: red">Orientation</span><span style="color: blue">="Horizontal" </span><span style="color: red">HorizontalAlignment</span><span style="color: blue">="Center" >
<</span><span style="color: #a31515">SilverlightApp</span><span style="color: blue">:</span><span style="color: #a31515">ChoiceControl </span><span style="color: red">Name</span><span style="color: blue">="choiceControl1" </span><span style="color: red">Heading</span><span style="color: blue">="Choice 1"/>
<</span><span style="color: #a31515">SilverlightApp</span><span style="color: blue">:</span><span style="color: #a31515">ChoiceControl </span><span style="color: red">Name</span><span style="color: blue">="choiceControl2" </span><span style="color: red">Heading</span><span style="color: blue">="Choice 2"/>
<</span><span style="color: #a31515">SilverlightApp</span><span style="color: blue">:</span><span style="color: #a31515">ChoiceControl </span><span style="color: red">Name</span><span style="color: blue">="choiceControl3" </span><span style="color: red">Heading</span><span style="color: blue">="Choice 3"/>
</</span><span style="color: #a31515">StackPanel</span><span style="color: blue">>
<</span><span style="color: #a31515">TextBlock </span><span style="color: red">Name</span><span style="color: blue">="statusText" </span><span style="color: red">TextAlignment</span><span style="color: blue">="Center"></</span><span style="color: #a31515">TextBlock</span><span style="color: blue">>
</</span><span style="color: #a31515">StackPanel</span><span style="color: blue">></span></pre>
<a href="http://11011.net/software/vspaste"></a>
<p>Now somehow I want to subscribe to the OptionSelections from each control, in such a way that I don’t see any results raised until an option from all three groups have been selected. After a few failed attempts, I stumbled upon this solution:</p>
<pre class="code"><span style="color: blue">public </span>MainPage()
{
InitializeComponent();
<span style="color: blue">string </span>formatString = <span style="color: #a31515">"Option {0}, Option {1}, Option {2}"</span>;
<span style="color: blue">var </span>selections = choiceControl1.OptionSelections
.CombineLatest(choiceControl2.OptionSelections, (i, j) => <span style="color: blue">new</span>[] { i, j })
.CombineLatest(choiceControl3.OptionSelections, (array, k) => <span style="color: blue">new</span>[] { array[0], array[1], k });
selections.Subscribe(values => statusText.Text = <span style="color: blue">string</span>.Format(formatString, values[0], values[1], values[2]));
}</pre>
<a href="http://11011.net/software/vspaste"></a>
<p>I’m using the CombineLatest extension method, but it will only combine two IObservables so I have to use it twice. The first call returns an IObservable<int[]>, where the array contains two elements. I then combine that with the option selections from choiceControl3, again returning an IObservable<int[]>, this time with all 3 selections. The final step is simply to subscribe to the resulting observable and display the message. </p>
<p>This solution of combining once into an array of two elements and then combining again into an array of three doesn’t seem particularly elegant, but so far I haven’t managed to find anything better. Perhaps I could write a version of CombineLatest that takes more than two observables and hides this ugliness? Its probably not necessary – there’s a good chance that the perfect method already exists, and I’ve just missed it. </p>
<p>In my next post, I’d like to demonstrate some of the failed attempts I made before I found CombineLatest. This demo will give me a chance to create my first IObservable<IObservable<T>>, which I’ve been itching to do :)</p>
<p>Today’s code has been <a href="http://github.com/paulbatum/Rx-sandpit/tree/Combination-Ex1">tagged</a> in my github repository.</p> Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com0tag:blogger.com,1999:blog-882821950355432699.post-86950969372306540192009-07-26T17:34:00.000+10:002009-07-26T17:43:05.389+10:00Reacting to the Reactive Framework: Part 5<p>It appears to have gone mostly under the radar, but the Reactive Framework is now out in the wild. The latest release of the <a href="http://www.codeplex.com/Silverlight">Silverlight Toolkit</a> includes System.Reactive.dll, mostly to facilitate the testing of the controls found within the toolkit. Jafar Husain broke the news earlier this week with <a href="http://themechanicalbride.blogspot.com/2009/07/introducing-rx-linq-to-events.html">this excellent post</a>.</p> <p>Today I want to do a demo that is very similar to the previous demos I’ve done, but of course this time I’ll be using the <strong>real Reactive Framework</strong> rather than my crappy attempt at implementing it that I’ve inflicted upon you in earlier posts. So far my experiments with using System.Reactive.dll with windows forms have not compiled properly so I’ll switch to using Silverlight for my examples. For now I will continue to focus on exposing button click events as an IObservable. Here is the code:</p> <pre class="code"><span style="color: #2b91af">IObservable</span><<span style="color: #2b91af">Event</span><<span style="color: #2b91af">RoutedEventArgs</span>>> clicks = <span style="color: #2b91af">Observable</span>.FromEvent<<span style="color: #2b91af">RoutedEventArgs</span>>(button1, <span style="color: #a31515">"Click"</span>);
<span style="color: blue">int </span>count = 0;
clicks.Subscribe(() => count++);
<span style="color: #2b91af">IObservable</span><<span style="color: blue">string</span>> messages = <span style="color: blue">from </span>c <span style="color: blue">in </span>clicks
<span style="color: blue">select string</span>.Format(<span style="color: #a31515">"Clicked {0} time{1}"</span>, count, count > 1 ? <span style="color: #a31515">"s" </span>: <span style="color: #a31515">""</span>);
messages.Subscribe(s => button1.Content = s);</pre>
<a href="http://11011.net/software/vspaste"></a>
<p>And here is the application:</p>
<iframe style="width: 200px; height: 200px" src="http://silverlight.services.live.com/invoke/104983/PB-Rx-Test1/iframe.html" frameborder="0" scrolling="no"></iframe>
<p>If you are in a RSS reader, you probably won’t be able to see the embedded Silverlight app above. Pop this post out into its own browser tab so that you can revel in the glory of a button that tells you how many times its been clicked! </p>
<p>Lets take a look at what this code is doing. The first step is to convert from an Event to an IObservable:</p>
<pre class="code"><span style="color: #2b91af">IObservable</span><<span style="color: #2b91af">Event</span><<span style="color: #2b91af">RoutedEventArgs</span>>> clicks = <span style="color: #2b91af">Observable</span>.FromEvent<<span style="color: #2b91af">RoutedEventArgs</span>>(button1, <span style="color: #a31515">"Click"</span>);</pre>
<p>The Observable class defines a large swath of extension methods for creating and manipulating IObservables. This overload of the FromEvent method is simple to use, but unfortunately it makes use of a magic string (“click”). There is another overload for FromEvent that allows us to do the same thing with compile-time safety, but it is more verbose. I’ve wrapped it in an extension method:</p>
<pre class="code"><span style="color: blue">public static </span><span style="color: #2b91af">IObservable</span><<span style="color: #2b91af">Event</span><<span style="color: #2b91af">RoutedEventArgs</span>>> GetClicks(<span style="color: blue">this </span><span style="color: #2b91af">Button </span>button)
{
<span style="color: blue">return </span><span style="color: #2b91af">Observable</span>.FromEvent((<span style="color: #2b91af">EventHandler</span><<span style="color: #2b91af">RoutedEventArgs</span>> genericHandler) => <span style="color: blue">new </span><span style="color: #2b91af">RoutedEventHandler</span>(genericHandler),
routedHandler => button.Click += routedHandler,
routedHandler => button.Click -= routedHandler);
}</pre>
<p><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a>This overload takes three functions as arguments. One to convert from a generic event handler (EventHandler<T>) to the specific event handler that the Click event uses (RoutedEventHandler). The conversion is straightforward, because the two event handlers have the same signature. The other two functions add and remove the handler. This extension method can be used like so:</p>
<pre class="code"><span style="color: #2b91af">IObservable</span><<span style="color: #2b91af">Event</span><<span style="color: #2b91af">RoutedEventArgs</span>>> clicks = button1.GetClicks();</pre>
<p>It would not surprise me if we eventually see extra libraries that define many of these extension methods for us. Ideally they would be unnecessary, and we could simply write:</p>
<pre class="code"><span style="color: #2b91af">IObservable</span><<span style="color: #2b91af">Event</span><<span style="color: #2b91af">RoutedEventArgs</span>>> clicks = button1.GetObservableEvent(b => b.Click);</pre>
<p>But unfortunately the dreaded <em>“The event 'System.Windows.Controls.Primitives.ButtonBase.Click' can only appear on the left hand side of += or –=”</em>  message rears its ugly head. Perhaps in C# 5 the story will be different.</p>
<p>Moving on, the code initializes a count variable and subscribes an increment function to the clicks:</p>
<pre class="code"><span style="color: blue">int </span>count = 0;
clicks.Subscribe(() => count++);</pre>
<p>You’ll notice that I am simply passing an Action to the Subscribe method, rather than an IObserver. The Reactive Framework won’t force you to use an IObserver if all you want to do is call a function when a new event occurs. </p>
<p>Finally, the code converts the stream of click events into a stream of messages and subscribes to it:</p>
<pre class="code"><span style="color: #2b91af">IObservable</span><<span style="color: blue">string</span>> messages = <span style="color: blue">from </span>c <span style="color: blue">in </span>clicks
<span style="color: blue">select string</span>.Format(<span style="color: #a31515">"Clicked {0} time{1}"</span>, count, count > 1 ? <span style="color: #a31515">"s" </span>: <span style="color: #a31515">""</span>);
messages.Subscribe(s => button1.Content = s);</pre>
<p>There are lots of other ways in which to rewrite today’s example code. This version is very short and still quite readable:</p>
<pre class="code"><span style="color: blue">int </span>count = 0;
button1.GetClicks().Select(x => ++count)
.Subscribe(() => button1.Content = <span style="color: blue">string</span>.Format(<span style="color: #a31515">"Clicked {0} time{1}"</span>, count, count > 1 ? <span style="color: #a31515">"s" </span>: <span style="color: #a31515">""</span>));</pre>
<p>Or I could implement IObserver:</p>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">CountingButtonObserver </span>: <span style="color: #2b91af">IObserver</span><<span style="color: #2b91af">Event</span><<span style="color: #2b91af">RoutedEventArgs</span>>>
{
<span style="color: blue">private int </span>_count = 0;
<span style="color: blue">public </span><span style="color: #2b91af">Button </span>Button { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
<span style="color: blue">public void </span>OnNext(<span style="color: #2b91af">Event</span><<span style="color: #2b91af">RoutedEventArgs</span>> value)
{
_count++;
Button.Content = <span style="color: blue">string</span>.Format(<span style="color: #a31515">"Clicked {0} time{1}"</span>, _count, _count > 1 ? <span style="color: #a31515">"s" </span>: <span style="color: #a31515">""</span>);
}
<span style="color: blue">public void </span>OnError(<span style="color: #2b91af">Exception </span>exception) {}
<span style="color: blue">public void </span>OnCompleted() {}
}</pre>
<a href="http://11011.net/software/vspaste"></a>
<p>And use it like so:</p>
<pre class="code">button1.GetClicks().Subscribe(<span style="color: blue">new </span><span style="color: #2b91af">CountingButtonObserver</span>{ Button = button1});</pre>
<p>Well, that’s probably enough for today. I’m going to continue to explore the Reactive Framework and see what interesting things I can find. Oh, and let me know if you come across any documentation for it – so far I haven’t found any and it can be quite a struggle to make sense of the various extension methods that are available.</p>
<p>I’ll be pushing my experiments with the Reactive Framework to a <a href="http://github.com/paulbatum/Rx-sandpit">github repo</a>.</p> Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com11tag:blogger.com,1999:blog-882821950355432699.post-68908360075368998152009-07-19T19:29:00.000+10:002009-07-19T19:30:02.248+10:00Reacting to the Reactive Framework: Part 4<p><em>This post is part 4 in a <a href="http://www.paulbatum.com/search/label/Reactive%20Framework">series</a>. </em></p> <p>About a week ago <a href="http://channel9.msdn.com/shows/Going+Deep/Expert-to-Expert-Brian-Beckman-and-Erik-Meijer-Inside-the-NET-Reactive-Framework-Rx/">another video</a> on the Reactive Framework went up, this time on Channel 9. It was an enjoyable video, though I found it tricky to follow in parts because my understanding of monad theory is virtually non-existent and the discussion does get abstract/theoretical in places. It did however give me a much better understanding of the basic Reactive Framework interfaces (IObserver<T> and IObservable<T>), which meant I had some work to do get my implementation up to scratch!</p> <p><em>Side note: I think I started this series badly by getting too complicated too fast, so I’m going to use this as an opportunity to start again.</em></p> <p>Here are the relevant interface definitions (I haven’t specified any covariance or contravariance for these types because I am still using C# 3.):</p> <pre class="code"><span style="color: blue">public interface </span><span style="color: #2b91af">IObservable</span><T>
{
<span style="color: #2b91af">IDisposable </span>Subscribe(<span style="color: #2b91af">IObserver</span><T> observer);
}
<span style="color: blue">public interface </span><span style="color: #2b91af">IObserver</span><T>
{
<span style="color: blue">void </span>OnNext(T item);
<span style="color: blue">void </span>OnDone();
<span style="color: blue">void </span>OnError(<span style="color: #2b91af">Exception </span>e);
}</pre>
<p>Hopefully the expected interaction between these two interfaces is relatively self-explanatory. There are a few differences between this pair of interfaces and what I had in the previous posts:</p>
<ul>
<li>Rather than passing a callback function to the Subscribe method (previously called ‘Attach’) an IObserver is passed. As you would expect, the OnNext(item) method is called on the subscribed observer when the IObservable has a new result. </li>
<li>The Subscribe method returns an IDisposable. When it is disposed, the IObserver is unsubscribed. </li>
<li>When the IObservable has finished (no more results), each of the IObservers are notified using OnDone(). </li>
<li>If the IObservable encounters an error, the IObservers are notified using OnError(e). </li>
</ul>
<p>The task today is to capture the stream of MouseDown events on a button as an IObservable<MouseEventArgs>, and then convert that into an IObservable<string> representing messages to be written to a text box. When the MouseDown event occurs, the text box should be updated accordingly. We can start by obtaining a IObservable<MouseEventArgs> like so:</p>
<pre class="code"><span style="color: #2b91af">IObservable</span><<span style="color: #2b91af">MouseEventArgs</span>> mouseEvents = button1.GetMouseDowns();</pre>
<a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a>
<p>GetMouseDowns() is an extension method – its purpose is to wrap the MouseDown event as an IObservable. Its implementation is very simple:</p>
<pre class="code"><span style="color: blue">public static </span><span style="color: #2b91af">IObservable</span><<span style="color: #2b91af">MouseEventArgs</span>> GetMouseDowns(<span style="color: blue">this </span><span style="color: #2b91af">Button </span>button)
{
<span style="color: blue">var </span>wrapper = <span style="color: blue">new </span><span style="color: #2b91af">EventWrapper</span><<span style="color: #2b91af">MouseEventArgs</span>>();
button.MouseDown += wrapper.Handler;
<span style="color: blue">return </span>wrapper;
}</pre>
<a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a>
<p>The EventWrapper class is wired up to the MouseDown event. It has a collection of observers which it notifies when the MouseDown event occurs:</p>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">EventWrapper</span><T> : <span style="color: #2b91af">IObservable</span><T> <span style="color: blue">where </span>T : <span style="color: #2b91af">EventArgs
</span>{
<span style="color: blue">private readonly </span><span style="color: #2b91af">ObserverCollection</span><T> _observers = <span style="color: blue">new </span><span style="color: #2b91af">ObserverCollection</span><T>();
<span style="color: blue">public void </span>Handler(<span style="color: blue">object </span>sender, T eventArgs)
{
_observers.NotifyNext(eventArgs);
}
<span style="color: blue">public </span><span style="color: #2b91af">IDisposable </span>Subscribe(<span style="color: #2b91af">IObserver</span><T> observer)
{
<span style="color: blue">return </span>_observers.Subscribe(observer);
}
}</pre>
<a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a>
<p>Lets skip the implementation of the ObserverCollection for now. I’d prefer to move on to converting this IObservable<MouseEventArgs> to an IObservable<string>:</p>
<pre class="code"><span style="color: #2b91af">IObservable</span><<span style="color: #2b91af">MouseEventArgs</span>> mouseEvents = button1.GetMouseDowns();
<span style="color: #2b91af">IObservable</span><<span style="color: blue">string</span>> messages = <span style="color: blue">from </span>md <span style="color: blue">in </span>mouseEvents
<span style="color: blue">select </span><span style="color: #a31515">"Mouse down at: " </span>+ md.X + <span style="color: #a31515">"\n"</span>;</pre>
<a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a>
<p>This works as long as the “Select” LINQ operator has been implemented for IObservable, because the C# compiler converts the above into:</p>
<pre class="code"><span style="color: #2b91af">IObservable</span><<span style="color: #2b91af">MouseEventArgs</span>> mouseEvents = button1.GetMouseDowns();
<span style="color: #2b91af">IObservable</span><<span style="color: blue">string</span>> messages = mouseEvents.Select( (<span style="color: #2b91af">MouseEventArgs </span>md) => <span style="color: #a31515">"Mouse down at: " </span>+ md.X + <span style="color: #a31515">"\n"</span>);</pre>
<a href="http://11011.net/software/vspaste"></a>
<p>The following extension method has the appropriate signature:</p>
<pre class="code"><span style="color: blue">public static </span><span style="color: #2b91af">IObservable</span><TResult> Select<T, TResult>(<span style="color: blue">this </span><span style="color: #2b91af">IObservable</span><T> observable, <span style="color: #2b91af">Func</span><T, TResult> func)
{
<span style="color: blue">return new </span><span style="color: #2b91af">SelectObservable</span><T, TResult>(observable, func);
}</pre>
<p>By calling this method, really what we’re saying is that we want a new IObservable that calls its subscribers when the old IObservable did, but first uses the passed function “func” to convert from the old result type to the new result type. In this case, that function is the lambda expression:</p>
<pre class="code">(<span style="color: #2b91af">MouseEventArgs </span>md) => <span style="color: #a31515">"Mouse down at: " </span>+ md.X + <span style="color: #a31515">"\n"</span></pre>
<p>Lets skip the implementation of the SelectObservable, and instead look at consuming the messages. I’ll subscribe an observer that will update the textbox:</p>
<pre class="code">messages.Subscribe(<span style="color: blue">new </span><span style="color: #2b91af">TextBoxUpdater</span>(textBox1));</pre>
<a href="http://11011.net/software/vspaste"></a>
<p>Here is the implementation for the TextBoxUpdater:</p>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">TextBoxUpdater </span>: <span style="color: #2b91af">IObserver</span><<span style="color: blue">string</span>>
{
<span style="color: blue">private readonly </span><span style="color: #2b91af">TextBox </span>_textBox;
<span style="color: blue">public </span>TextBoxUpdater(<span style="color: #2b91af">TextBox </span>textBox)
{
_textBox = textBox;
}
<span style="color: blue">private void </span>AppendText(<span style="color: blue">string </span>text)
{
<span style="color: #2b91af">Action </span>textboxUpdater = () => _textBox.AppendText(text);
_textBox.BeginInvoke(textboxUpdater);
}
<span style="color: blue">public void </span>OnNext(<span style="color: blue">string </span>s)
{
AppendText(s);
}
<span style="color: blue">public void </span>OnDone()
{
AppendText(<span style="color: #a31515">"Done\n"</span>);
}
<span style="color: blue">public void </span>OnError(<span style="color: #2b91af">Exception </span>e)
{
AppendText(<span style="color: #a31515">"Error: " </span>+ e.Message);
}
}</pre>
<a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a>As you can see, it implements the OnNext, OnDone and OnError methods by writing some appropriate text, though in this simple example, I’m not really using OnDone or OnError. If I run this program now and click the button a few times, I get this:
<p><a href="http://lh6.ggpht.com/_AP_-f1YlmB4/SmLnlYCiRGI/AAAAAAAAAO0/ETzF21lZagA/s1600-h/image%5B6%5D.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="302" alt="image" src="http://lh6.ggpht.com/_AP_-f1YlmB4/SmLnmCoj38I/AAAAAAAAAO4/ZXhjj-a1VrI/image_thumb%5B2%5D.png?imgmax=800" width="304" border="0" /></a> </p>
<p>That wraps it up for today. The code as of this post is available <a href="http://github.com/paulbatum/Reactive/tree/pt4-example">here</a>.</p> Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com2tag:blogger.com,1999:blog-882821950355432699.post-33056224746919912812009-07-05T15:08:00.001+10:002009-07-05T15:09:34.374+10:00Reacting to the Reactive Framework: Part 3<p>In <a href="http://www.paulbatum.com/2009/05/reacting-to-reactive-framework-part-1.html">part one</a> of this series, I introduced the Live Labs Reactive Framework and provided a simple example of what can be achieved when using LINQ for reactive programming. In <a href="http://www.paulbatum.com/2009/05/reacting-to-reactive-framework-part-2.html">part two</a> I did my best to explain how my example worked. In today’s post I want to extend the example slightly. Just to reiterate, this series is not about using the Live Labs Reactive Framework as it has not yet been released. I’m exploring the idea of a reactive framework using my own implementation.</p> <p>Here is my example from the previous posts:</p> <pre class="code"><span style="color: rgb(43,145,175)">Func</span><<span style="color: rgb(43,145,175)">MouseEventArgs</span>, <span style="color: blue">int</span>> slowOperation = args =>
{
System.Threading.<span style="color: rgb(43,145,175)">Thread</span>.Sleep(3000);
<span style="color: blue">return </span>args.X;
};
<span style="color: rgb(43,145,175)">IObservable</span><<span style="color: blue">int</span>> observable = <span style="color: blue">from </span>md <span style="color: blue">in </span>button1.GetMouseDowns()
<span style="color: blue">from </span>x <span style="color: blue">in </span>slowOperation.AsAsyncObservable(md.EventArgs)
<span style="color: blue">select </span>x;</pre>
<p>The idea behind this code is that the IObservable<int> represents a stream of integers that are the result of capturing the mouse down event on a button, doing some “slow processing” (really just a 3 second sleep) asynchronously, and returning the x coordinate from the mouse down event. You can then attach something to that observable like so:</p>
<pre class="code"><span style="color: rgb(43,145,175)">Action</span><<span style="color: blue">string</span>> textboxUpdater = s => textBox1.AppendText(s);
observable.Attach(x => textBox1.BeginInvoke(textboxUpdater, <span style="color: rgb(163,21,21)">"Mouse down: " </span>+ x + <span style="color: rgb(163,21,21)">"\n"</span>));</pre>
<p>The attached code updates the textbox as the values bubble up through the IObservable. Unfortunately its a little more complicated than I would like because the update has to be marshalled onto the UI thread – hence the BeginInvoke call. Today I want to modify this example so that the textbox is only updated when the right mouse button was clicked. The MouseEventArgs can tell me which button was clicked, so really this is just a matter of implementing support for <em>where</em>:</p>
<pre class="code"><span style="color: #2b91af">IObservable</span><<span style="color: blue">int</span>> observable = <span style="color: blue">from </span>md <span style="color: blue">in </span>button1.GetMouseDowns()
<span style="color: blue">where </span>md.EventArgs.Button == <span style="color: #2b91af">MouseButtons</span>.Right
<span style="color: blue">from </span>x <span style="color: blue">in </span>slowOperation.AsAsyncObservable(md.EventArgs)
<span style="color: blue">select </span>x;</pre>
<p>Well this is a very natural way to express what I want – and the implementation is not too hard. First I create the appropriate extension method:</p>
<pre class="code"><span style="color: blue">public static </span><span style="color: #2b91af">IObservable</span><T> Where<T>(<span style="color: blue">this </span><span style="color: #2b91af">IObservable</span><T> source, <span style="color: #2b91af">Func</span><T, <span style="color: blue">bool</span>> predicate)
{
<span style="color: blue">return new </span><span style="color: #2b91af">WhereObservable</span><T>(source, predicate);
}</pre>
<p><a href="http://11011.net/software/vspaste"></a>This extension method is just a wrapper call for a class. In this case, its WhereObservable<T> which takes a source IObservable, and a predicate to apply:</p>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">WhereObservable</span><T> : <span style="color: #2b91af">IObservable</span><T>
{
<span style="color: blue">private readonly </span><span style="color: #2b91af">IObservable</span><T> _source;
<span style="color: blue">private readonly </span><span style="color: #2b91af">Func</span><T, <span style="color: blue">bool</span>> _predicate;
<span style="color: blue">public </span>WhereObservable(<span style="color: #2b91af">IObservable</span><T> source, <span style="color: #2b91af">Func</span><T, <span style="color: blue">bool</span>> predicate)
{
_source = source;
_predicate = predicate;
}
<span style="color: blue">public void </span>Attach(<span style="color: #2b91af">Action</span><T> action)
{
_source.Attach(t => { <span style="color: blue">if </span>(_predicate(t)) action(t); });
}
}</pre>
<p>All I’m doing here is wrapping an inner observable so that I can check to see if the predicate applies before I let the observable event bubble up. That’s all there is to it. My example will now only update the textbox if the right mouse button was clicked.</p>
<p>My work on this project is <a href="http://github.com/paulbatum/Reactive">available</a> on github. To get the code as it was at the time this post was written, use this <a href="http://github.com/paulbatum/Reactive/tree/pt3-example">tag</a>.</p> Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com2tag:blogger.com,1999:blog-882821950355432699.post-4708531754636644272009-05-31T15:42:00.000+10:002009-07-05T15:09:34.375+10:00Reacting to the Reactive Framework: Part 2<p><strong>DISCLAIMER: The code in this post was the result of a big hackfest with the single goal of getting a particular use case working. I am telling you right now that I paid no attention to potential concurrency problems and that if you try to reuse any of this stuff you are just asking for trouble.</strong></p> <p>In the <a href="http://www.paulbatum.com/2009/05/reacting-to-reactive-framework-part-1.html">previous post</a>, I explained how Eric Meijer’s recent Lang.NET presentation on the LiveLabs Reactive Framework piqued my interest. Wondering how the framework works, I decided to have a go at emulating some of the basic functionality it appears to provide. This code demonstrates the functionality I’ve implemented so far:</p> <pre class="code"><span style="color: #2b91af">Func</span><<span style="color: #2b91af">MouseEventArgs</span>, <span style="color: blue">int</span>> slowOperation = args =>
{
System.Threading.<span style="color: #2b91af">Thread</span>.Sleep(3000);
<span style="color: blue">return </span>args.X;
};
<span style="color: #2b91af">IObservable</span><<span style="color: blue">int</span>> observable = <span style="color: blue">from </span>md <span style="color: blue">in </span>button1.GetMouseDowns()
<span style="color: blue">from </span>x <span style="color: blue">in </span>slowOperation.AsAsyncObservable(md.EventArgs)
<span style="color: blue">select </span>x;
<span style="color: #2b91af">Action</span><<span style="color: blue">string</span>> textboxUpdater = s => textBox1.AppendText(s);
observable.Attach(x => textBox1.BeginInvoke(textboxUpdater, <span style="color: #a31515">"Mouse down: " </span>+ x + <span style="color: #a31515">"\n"</span>));</pre>
<p>Today I am going to work my way through the query comprehension you can see here and do my best to explain how I got this working. Perhaps a good place to start would be to convert the query comprehension into a method chain in the same way the C# compiler does for us under the covers. Resharper can do this automatically, which is convenient:</p>
<pre class="code"><span style="color: #2b91af">IObservable</span><<span style="color: blue">int</span>> observable = button1.GetMouseDowns().SelectMany(
md => slowOperation.AsAsyncObservable(md.EventArgs),
(md, x) => x
);</pre>
<p>The first call here is to an extension method called GetMouseDowns:</p>
<pre class="code"><span style="color: blue">public static </span><span style="color: #2b91af">IObservable</span><<span style="color: #2b91af">EventResult</span><<span style="color: #2b91af">Button</span>, <span style="color: #2b91af">MouseEventArgs</span>>> GetMouseDowns(<span style="color: blue">this </span><span style="color: #2b91af">Button </span>b)
{
<span style="color: blue">var </span>wrapper = <span style="color: blue">new </span><span style="color: #2b91af">EventWrapper</span><<span style="color: #2b91af">Button</span>, <span style="color: #2b91af">MouseEventArgs</span>>();
b.MouseDown += wrapper.Handle;
<span style="color: blue">return </span>wrapper;
}</pre>
<p>So far, this is relatively straightforward. The GetMouseDowns extension method creates an EventWrapper, and wires that EventWrapper up to the MouseDown event on the button. You can see that the wrapper is being returned as an IObservable of an EventResult. Here is the code for these:</p>
<pre class="code"><span style="color: blue">public interface </span><span style="color: #2b91af">IObservable</span><T>
{
<span style="color: blue">void </span>Attach(<span style="color: #2b91af">Action</span><T> action);
}</pre>
<a href="http://11011.net/software/vspaste"></a>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">EventResult</span><TSender, TArgs>
{
<span style="color: blue">public </span>EventResult(TSender sender, TArgs args)
{
Sender = sender;
EventArgs = args;
}
<span style="color: blue">public </span>TSender Sender { <span style="color: blue">get</span>; <span style="color: blue">private set</span>; }
<span style="color: blue">public </span>TArgs EventArgs { <span style="color: blue">get</span>; <span style="color: blue">private set</span>; }
}</pre>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">EventWrapper</span><TSender, TArgs> : <span style="color: #2b91af">IObservable</span><<span style="color: #2b91af">EventResult</span><TSender,TArgs>>
{
<span style="color: blue">private </span><span style="color: #2b91af">List</span><<span style="color: #2b91af">Action</span><<span style="color: #2b91af">EventResult</span><TSender, TArgs>>> _attached = <span style="color: blue">new </span><span style="color: #2b91af">List</span><<span style="color: #2b91af">Action</span><<span style="color: #2b91af">EventResult</span><TSender, TArgs>>>();
<span style="color: blue">public void </span>Handle(<span style="color: blue">object </span>sender, TArgs e)
{
<span style="color: blue">foreach </span>(<span style="color: blue">var </span>action <span style="color: blue">in </span>_attached)
action(<span style="color: blue">new </span><span style="color: #2b91af">EventResult</span><TSender,TArgs>((TSender)sender, e ));
}
<span style="color: blue">public void </span>Attach(<span style="color: #2b91af">Action</span><<span style="color: #2b91af">EventResult</span><TSender, TArgs>> action)
{
_attached.Add(action);
}
}</pre>
<p>Now there is some really naive code here. What would happen if someone called Attach while we were in the middle of handling the event? It would crash, because the list of actions to be called would be modified while it was being iterated over. In general, the code for the EventWrapper feels bad. I am sure it can be done much better, but it works for now.</p>
<p>So the result of the GetMouseDowns method is an EventWrapper that will call the attached methods when the mouse down event occurs, and this is exposed as an IObservable. SelectMany is then called on that IObservable. This is another extension method:</p>
<pre class="code"><span style="color: blue">public static </span><span style="color: #2b91af">IObservable</span><TResult> SelectMany<TSource, TCollection, TResult>(<span style="color: blue">this </span><span style="color: #2b91af">IObservable</span><TSource> source, <span style="color: #2b91af">Func</span><TSource, <span style="color: #2b91af">IObservable</span><TCollection>> collectionSelector, <span style="color: #2b91af">Func</span><TSource, TCollection, TResult> resultSelector)
{
<span style="color: blue">return new </span><span style="color: #2b91af">SelectManyObservable</span><TSource, TCollection, TResult>(source, collectionSelector, resultSelector);
}</pre>
<p>So how on earth did I arrive at this method? Its quite simple actually – I stole its signature from the SelectMany extension method implemented on IEnumerable. The interesting thing about LINQ query comprehensions is that they actually don’t have a dependence on IEnumerable or IQueryable. Instead they depend on the existence of particular methods with the appropriate signature such as Select, SelectMany, Where, GroupBy, etc. By writing these extension methods for IObservable, I can then write query comprehensions against IObservables.</p>
<p>Once its established that my SelectMany borrowed its signature from the appropriate extension method on IEnumerable, there isn’t much more to know about it. You can see that all it simply does is return a SelectManyObservable that wraps the passed arguments. What is the SelectManyObservable exactly? Well, here is the code:</p>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">SelectManyObservable</span><TSource, TCollection, TResult> : <span style="color: #2b91af">IObservable</span><TResult>
{
<span style="color: blue">private readonly </span><span style="color: #2b91af">IObservable</span><TSource> _source;
<span style="color: blue">private readonly </span><span style="color: #2b91af">Func</span><TSource, <span style="color: #2b91af">IObservable</span><TCollection>> _collectionSelector;
<span style="color: blue">private readonly </span><span style="color: #2b91af">Func</span><TSource, TCollection, TResult> _resultSelector;
<span style="color: blue">public </span>SelectManyObservable(<span style="color: #2b91af">IObservable</span><TSource> source, <span style="color: #2b91af">Func</span><TSource, <span style="color: #2b91af">IObservable</span><TCollection>> collectionSelector, <span style="color: #2b91af">Func</span><TSource, TCollection, TResult> resultSelector)
{
_source = source;
_collectionSelector = collectionSelector;
_resultSelector = resultSelector;
}
<span style="color: blue">public void </span>Attach(<span style="color: #2b91af">Action</span><TResult> action)
{
_source.Attach(
s => _collectionSelector(s).Attach(
c => action(_resultSelector(s, c))
)
);
}
}</pre>
<p>So this class simply wraps an underlying IObservable, and when methods are attached to the SelecyManyObservable, it actually gets attached to the underlying IObservable. The funny thing about this code is that it practically wrote itself. It was basically a matter of just figuring out how the underlying observable, collectionSelector, resultSelector and attached action related to each other and then calling them accordingly. It felt like solving a 4 piece jigsaw puzzle with only 1 solution.</p>
<p>Before the explanation of the query comprehension is complete, there is one more extension method that requires explanation:</p>
<pre class="code"><span style="color: blue">public static </span><span style="color: #2b91af">IObservable</span><TResult> AsAsyncObservable<TInput, TResult>(<span style="color: blue">this </span><span style="color: #2b91af">Func</span><TInput,TResult> funcToObserve,TInput input)
{
<span style="color: blue">return new </span><span style="color: #2b91af">AsyncWrapper</span><TInput, TResult>(funcToObserve, input);
}</pre>
<a href="http://11011.net/software/vspaste"></a>
<p>This pattern should look familiar. Its like the SelectMany in that it simply returns a wrapper object that takes all the method arguments as parameters. The signature however, wasn’t borrowed from the framework. The point of this method is to allow the user to convert an anonymous delegate or lambda expression into an IObservable. Now I hope you packed the goggles I mentioned in my previous post, because AsyncWrapper is really nasty:</p>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">AsyncWrapper</span><TInput, TResult> : <span style="color: #2b91af">IObservable</span><TResult>
{
<span style="color: blue">private </span><span style="color: #2b91af">List</span><<span style="color: #2b91af">Action</span><TResult>> _attached = <span style="color: blue">new </span><span style="color: #2b91af">List</span><<span style="color: #2b91af">Action</span><TResult>>();
<span style="color: blue">public </span>AsyncWrapper(<span style="color: #2b91af">Func</span><TInput, TResult> funcToObserve, TInput input)
{
funcToObserve.BeginInvoke(input, CompletedCallback, <span style="color: blue">null</span>);
}
<span style="color: blue">public void </span>Attach(<span style="color: #2b91af">Action</span><TResult> action)
{
_attached.Add(action);
}
<span style="color: blue">private void </span>CompletedCallback(<span style="color: #2b91af">IAsyncResult </span>asyncResult)
{
TResult calculatedValue = ((<span style="color: #2b91af">Func</span><TInput, TResult>) ((<span style="color: #2b91af">AsyncResult</span>) asyncResult).AsyncDelegate).EndInvoke(
asyncResult);
<span style="color: blue">foreach </span>(<span style="color: blue">var </span>action <span style="color: blue">in </span>_attached)
action(calculatedValue);
}
}</pre>
<p>It might not seem so bad, until you look at what the constructor is doing. When the AsyncWrapper is created, it fires off the function to observe. Now when that function completes, the callback will be invoked, and as a result all the attached actions will also be invoked. The reason why this is all so heinous is that the actions will have to be attached AFTER the function to observe is invoked, but before it completes. As a result, I am fairly sure that if we changed the slow asynchronous operation to be much faster, then this code would stop working. Surely a better solution can be found, and I do hope to attend to this later.</p>
<p>So that covers all the code that makes my example work. The nice thing about this approach is the composability. It is convenient to be able to work with enumerables using select, where, etc and the same is true for observables. I am really looking forward to getting my hands on the Reactive Framework code. In the mean time, I’ll continue to experiment. In the next post I’ll extend this example, starting with adding support for ‘where’ operations.</p> Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com0tag:blogger.com,1999:blog-882821950355432699.post-36021398690192377132009-05-26T22:54:00.001+10:002009-07-05T15:09:34.375+10:00Reacting to the Reactive Framework: Part 1<p>Last night I managed to get some code working and I was very excited, but it was far too late to start writing a blog post. Here is the code:</p> <pre class="code"><span style="color: #2b91af">Func</span><<span style="color: #2b91af">MouseEventArgs</span>, <span style="color: blue">int</span>> slowOperation = args =>
{
System.Threading.<span style="color: #2b91af">Thread</span>.Sleep(3000);
<span style="color: blue">return </span>args.X;
};
<span style="color: #2b91af">IObservable</span><<span style="color: blue">int</span>> observable = <span style="color: blue">from </span>md <span style="color: blue">in </span>button1.GetMouseDowns()
<span style="color: blue">from </span>x <span style="color: blue">in </span>slowOperation.AsAsyncObservable(md.EventArgs)
<span style="color: blue">select </span>x;
<span style="color: #2b91af">Action</span><<span style="color: blue">string</span>> textboxUpdater = s => textBox1.AppendText(s);
observable.Attach(x => textBox1.BeginInvoke(textboxUpdater, <span style="color: #a31515">"Mouse down: " </span>+ x + <span style="color: #a31515">"\n"</span>));</pre>
<a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a>
<p></p>
<p>This code is sitting inside a very simple windows form. The form has a button and a textbox. When the button is clicked, a message is written to the textbox about 3 seconds later, relaying the relative X coordinate of the mouse when the button was clicked. The 3 second delay represents some sort of slow asynchronous operation, currently simulated with a simple Thread.Sleep(). Because the slow operation is done on a different thread, we have to use Control.BeginInvoke() to get the textbox to update on the UI thread. GetMouseDowns() is an extension method on Button that helps set the whole thing up by returning an IObservable that is wired to the MouseDown event.</p>
<p>So at this point you might be wondering what this is all about. To get the full story, I encourage you to watch Eric Meijer’s video on the LiveLabs Reactive Framework (<a href="http://download.microsoft.com/download/7/6/A/76A69AE5-72B5-4005-BBD9-7EA5F4795014/23-ErikMeijer-LiveLabsReactiveFramework.wmv">direct wmv link</a>). In this very enjoyable presentation, Eric gives us a run down the Reactive Framework, which appears to be a set of libraries that unite various types of “reactive” operations under a common pair of interfaces, IObserver<T> and IObservable<T> which are then integrated into LINQ. I found the presentation to be quite a tease. Erik shows just enough to give you an idea of what the Reactive Framework is all about, but he skims over the implementation details quite lightly. I ended up watching the thing a couple of times, trying to wrap my head around the idea of LINQ query comprehensions (e.g. from x in y select x.ID) operating against non enumerable/queryable types. In particular, I started wondering whether I could implement something like the code from this slide:</p>
<p><a href="http://lh3.ggpht.com/_AP_-f1YlmB4/ShvmhNrLXVI/AAAAAAAAAOQ/g0JZE7ls3Qo/s1600-h/image%5B4%5D.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_AP_-f1YlmB4/ShvmiuK3oeI/AAAAAAAAAOU/On8RuQREjGQ/image_thumb%5B2%5D.png?imgmax=800" width="623" height="484" /></a> </p>
<p>As you can see, my code at the top is not too dissimilar from Erik’s code here. Erik’s example is a web page with dictionary suggest on a textbox. When the user enters a character into the textbox, the dictionary suggest runs asynchronously against the input entered so far and when a return value is received it is rendered as html. </p>
<p>There is certainly quite a lot regarding the Reactive Framework that I don’t understand. I’ve been unable to find any resources beyond Erik’s talk – certainly the code doesn’t seem available anywhere. So far I don’t even understand how IObserver fits in. Can YOU see anything that might implement IObserver in the above slide? But in any case, the idea is intriguing, and trying to figure out how to do this myself is teaching me quite a bit about LINQ. In the next post, I’ll do my best to explain how the implementation works. Don’t forget your goggles, this is some pretty hacky code coming up. </p> Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com7tag:blogger.com,1999:blog-882821950355432699.post-42898747053706405242009-04-29T01:20:00.001+10:002009-04-29T01:20:53.404+10:00A Fluent NHibernate update<p>Since James has <a href="http://www.lostechies.com/blogs/jagregory/archive/2009/04/28/what-s-been-happening-in-fluent-nhibernate-land.aspx">announced</a> the latest happenings in the ongoing saga of moving Fluent NHibernate to using a semantic model, I thought a companion post might be appropriate.</p> <p>My <a href="http://www.paulbatum.com/2008/12/fluent-nhibernate-rewrite.html">first post</a> on the Fluent NHibernate rewrite is as good a place to start as any. In it I explained the limitations of the existing implementation and outlined my strategy for dissolving those limitations. My branch differs from the trunk by separating the fluent interface from the mapping model. The fluent interface manipulates the underlying model, and a family of visitors build a Hbm object graph that represents that underlying model. That object graph is serialized to xml and then passed to NHibernate. This graph consists of classes that are generated from the NHibernate mapping schema, so the serialization step is all automatic and works flawlessly.</p> <p>The use of the visitor pattern allows for two things. One, the mapping model is not tied to any particular output format. Sure we pass NHibernate xml today, but tomorrow it would be nice to pass it the Hbm object graph directly so it can skip the xml schema validation step. The day after it would be nice to pass it a prebuilt NHibernate.Mapping graph, which is an idea that <a href="http://tunatoksoz.com/">Tuna Toksoz</a> was exploring from within my branch. Secondly, the visitor implementation allowed for powerful manipulations of the mapping model that would otherwise be difficult. I talked more about the visitor implementation <a href="http://www.paulbatum.com/2009/02/fluent-nhibernate-semantic-model_21.html">here</a>.</p> <p>Sure, passing NHibernate its mappings in a format other than xml would be nice some day, but there was another reason why I chose to use a Hbm graph instead of directly writing xml. Basically, its much harder to go off the rails when working with the Hbm objects. One example is that the NHibernate schema is finicky about element ordering and you simply don’t have to worry about this when working with Hbm objects.</p> <p>As time went on the code base grew, things changed, but slow and steady progress was made. The problem is that slow and steady doesn’t always win the race – specifically in the case where the goalpost is moving as fast or faster than you! This is the classic rewrite problem. I’m sure you are familiar with it – its why all the well respected software professionals tell you that rewriting your app is a fools errand. And don’t get me wrong, I am in agreement here. I approached my work to rewrite Fluent NHibernate as a prototyping exercise - “one possible future” if you will. As the work continued I would discuss our long term goals with James and for a while we found ourselves hoping that we could replace the existing trunk with my branch, if only we could “catch up” to the trunk functionality. Of course this sort of thinking was dangerous, and the consequences are well described in James’s post. My intentions, while good, have lead to a lack of progress on the Fluent NHibernate trunk and this is simply not a healthy place to be.</p> <p>James asked me whether I could see a way to merge the two code bases. Basically inject my model into the existing guts of the trunk. I told him I couldn’t see a way how, but I encouraged him to try. The problem, I’m sure you’ve already guessed, is that I was too “caught up” in my code and simply not prepared to make sacrifices. This is why James managed something that I could not – he merged my branch into the trunk code under an “integration”  branch, with all the existing trunk tests passing. Its not pretty, but I suspect that it represents the best direction to work from. We can now do what the experts tell us to do and refactor, rather than rewrite.</p> <p>So what were the sacrifices? The main one is the Hbm object graph approach. Fluent NHibernate will only be capable of spitting out xml for the near future. Lets face it, its not a huge loss. Plus I say near future because the visitor implementation survived, so there is no reason why we couldn’t later start retrofitting my Hbm code in. I am yet to take full stock of the “casualties”, but I expect that everything that has been lost in the merge can be regained through a gradual process of refactoring and reintroducing code and ideas from my branch. It will be fun!</p> <p>Finally I want to use this post as an opportunity to thank James for all his amazingly hard work on this great project. We don’t always see eye to eye but the thing that I often remind myself is that time and again he has proven to me that he has his finger on the pulse of our users and can see how this project can best fulfil their needs. Please keep it up James.</p> Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com2tag:blogger.com,1999:blog-882821950355432699.post-19589711088481679342009-04-27T14:26:00.001+10:002009-04-27T14:26:35.853+10:00Legacy code: a follow up<p>A few weeks back I wrote a <a href="http://www.paulbatum.com/2009/04/working-effectively-with-legacy-code.html">post</a> on <em>Working Effectively with Legacy Code</em>, a book by Michael Feathers. At the time I lamented that even though I accepted Michael’s definition of legacy code (code without tests), I wasn’t doing much about it – I hadn’t written any tests at work. Today I wanted to follow up on this because the last two weeks have gone much better – I’ve been writing unit tests. I was given the job of rewriting a particularly hairy module and this was simply too good an opportunity to pass up. I’m not doing TDD yet, and I certainly haven’t written as many tests as I would like, but its a start.</p> <p>Rather than using a mocking framework, I’ve been hand rolling stubs. I believe that the other developers will have an easier time understanding the tests if I use manual stubs. Mocking frameworks are certainly convenient but as Michael demonstrates in his book, they are not necessary <em>per se</em>. So far I haven’t found this particularly painful and I think its a sound approach for introducing automated unit testing. I must admit that the fact that I am working on a .NET 2.0 project made this decision easier. I learned Rhino Mocks using the .NET 3.5 API and I think I would have a hard time going without the sweetness that lambda expressions provide.</p> <p>Writing that very first test is a bit of a barrier, but its only a mental one. I was fortunate to have a nice piece of work come along and give me a push. Hopefully it will not be necessary the next time I find myself faced with legacy code – I intend to write that first test without a moment of hesitation. Its all downhill from there.</p> Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com0tag:blogger.com,1999:blog-882821950355432699.post-47348497229417247372009-04-13T23:04:00.001+10:002009-04-13T23:04:36.471+10:00Working Effectively with Legacy Code<img style="display: inline; margin-left: 0px; margin-right: 0px" border="0" alt="Working Effectively with Legacy Code (Robert C. Martin Series)" align="right" src="http://ecx.images-amazon.com/images/I/51RCXGPXQ8L._SL500_AA240_.jpg" width="240" height="240" /> <p>Today I finished reading <em>Working Effectively with Legacy Code</em> by Michael Feathers. If you are not familiar with this book, you might be wondering if I’ve somehow been roped into maintaining some sort of 10 year old VB6 application -fortunately this is not the case. But I am indeed working on a legacy application – at least, it is legacy by Michael’s rather unique definition. Michael defines legacy code as code that is not under test, specifically unit tests. By Michael’s definition, virtually all of the code I have written during my career was legacy from the day it was born, and when I reflect on it, this seems like a fair statement. Here is a short excerpt from the preface:</p> <blockquote> <p><em>Code without tests is bad code. It doesn’t matter how well written it is; it doesn’t matter how pretty or object-oriented or well-encapsulated it is. With tests, we can change the behaviour of our code quickly and verifiably. Without them, we really don’t know if our code is getting better or worse.</em></p> </blockquote> <p>It doesn’t matter how clean and refactored my code was – developers that had to maintain it were forced to do so with uncertainty. It is specifically that element of uncertainty that I associate with the legacy code experience.</p> <p>The book uses a FAQ format, with chapter titles such as: </p> <ul> <li>I need to make a change. What methods should I test?</li> <li>I can’t get this class into a test harness.</li> <li>This class is too big and I don’t want it to get any bigger.</li> <li>I need to make a change but I don’t know what tests to write.</li> </ul> <p>It does a great job of illustrating refactorings that let you break dependencies so you can get the code under test. These refactorings are designed to be performed safely without tests so you can get the tests written and then move on to more significant refactorings. The book also does a great job of tackling the mechanics of writing the tests themselves. </p> <p>I think the book could have been better named. Ayende <a href="http://ayende.com/Blog/archive/2005/08/28/BookReviewWorkingEffectivelyWithLegacyCode.aspx">says</a> that it should be mandatory reading for people that write code for a living. I agree with him, but the title does not communicate this. In general I found it very readable and relatively quick to get through, and the lessons the book offers are profound.</p> <p>So the obvious question is whether it has changed the way I’ve been writing code. Well unfortunately, I wrote a bunch of legacy code just last week! By night I revel in the freedom that my unit tests give me as I work on Fluent NHibernate, but by day I continue to work in a manner that Uncle Bob would consider <a href="http://www.infoq.com/interviews/coplien-martin-tdd">unprofessional</a>. Why?</p> <p>Unfortunately the book doesn’t have a chapter called “<em>I’m all alone, nobody else is convinced that writing unit tests is worthwhile. Is it worth starting if its just me doing it?</em>”. Nor does it have a “<em>This is just a quick fix for someone else’s broken code, I’ll write tests when the –real- work begins</em>” chapter (its a weak argument but I’ve found it an easy trap to fall into). The closest the book comes is the very last FAQ chapter: “<em>We feel overwhelmed. It isn’t going to get any better</em>”. But at less than 2 pages, it didn’t quite deliver what I needed to hear.</p> <p>I’m finding it difficult to take that first step and add that 55th project to the solution (yeah…) so I can write some tests. Part of it is procrastination, but part of it is fear. I believe these ideas have value and I don’t want to screw it up. But simply “waiting until the time is right” is the refrain of the procrastinator. </p> <p>This makes me feel that Working with Legacy Code is a great book, but not an entirely complete package. It gives you the tools and techniques but assumes that the reader can simply read it and run with it. Michael developed these techniques as he worked with teams that heeded his advice and were prepared to follow his lead. A piece of the puzzle is missing because Michael has been the consultant for so long.</p> <p>Maybe this criticism is unfair. People can write books full of advice, but its up to the reader to start putting that advice into practice. A new work week begins tomorrow, perhaps I’ll add that 55th project before I do anything else tomorrow morning.</p> Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com5tag:blogger.com,1999:blog-882821950355432699.post-30673257773065087212009-03-09T16:30:00.000+11:002009-03-09T16:33:45.897+11:00Supporting multiple NHibernate versions in Fluent NHibernate semantic model<p>My <a href="http://fluentnhibernate.org">Fluent NHibernate</a> semantic model rewrite is designed to support multiple versions of NHibernate simultaneously. At the moment, I support NH 2.0.1GA and 2.1.0.1001 (this was a trunk snapshot). My goal is to support the latest official release and to keep as up to date with the trunk as possible; time will tell how well this pans out. </p> <p>The semantic model rewrite makes heavy use of classes that are generated from the NH mapping schema. These classes are all prefixed with Hbm, so I am in the habit of calling them “Hbm*” classes. Here is some example code that builds a HbmKey representation of a KeyMapping:</p><pre class="code"><span style="color: blue">public override void </span>ProcessKey(<span style="color: #2b91af">KeyMapping </span>keyMapping)
{
_hbm = <span style="color: blue">new </span><span style="color: #2b91af">HbmKey</span>();
<span style="color: blue">if </span>(keyMapping.Attributes.IsSpecified(x => x.Column))
_hbm.column1 = keyMapping.Column;
<span style="color: blue">if </span>(keyMapping.Attributes.IsSpecified(x => x.ForeignKey))
_hbm.foreignkey = keyMapping.ForeignKey;
<span style="color: blue">if </span>(keyMapping.Attributes.IsSpecified(x => x.PropertyReference))
_hbm.propertyref = keyMapping.PropertyReference;
<span style="color: blue">if </span>(keyMapping.Attributes.IsSpecified(x => x.CascadeOnDelete))
_hbm.SetCascadeOnDelete(keyMapping.CascadeOnDelete);
}</pre><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a>
<p>Because the NH mapping schema changes from version to version, the public interface for these classes also changes from version to version. See that “column1” property? Its entirely possible it was called “column” in an earlier version of NH. Obviously, if it were to change back to “column” tomorrow, this code would no longer compile. Given this, how can Fluent NH hope to simultaneously support multiple NH versions? The answer is to put any version specific code in a separate assembly.</p>
<p>Today I will fix a NH2.1 incompatibility that I introduced a few days ago when adding the ability to specify the column name for a property. Here is the code I wrote while working against NH2.0.1:</p><pre class="code"><span style="color: blue">public override void </span>ProcessProperty(<span style="color: #2b91af">PropertyMapping </span>propertyMapping)
{
_hbm = <span style="color: blue">new </span><span style="color: #2b91af">HbmProperty</span>();
_hbm.name = propertyMapping.Name;
<span style="color: blue">if</span>(propertyMapping.Attributes.IsSpecified(x => x.IsNotNullable))
_hbm.SetNotNull(propertyMapping.IsNotNullable);
<span style="color: blue">if </span>(propertyMapping.Attributes.IsSpecified(x => x.Length))
_hbm.length = propertyMapping.Length.ToString();
<span style="color: blue">if </span>(propertyMapping.Attributes.IsSpecified(x => x.ColumnName))
_hbm.column1 = propertyMapping.ColumnName;
}</pre><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a>
<p>The very last line is the one to watch here. You can see its setting the “column1” property. This worked fine against NH2.0.1 but when I ran my rake script to switch over to NH2.1 today, this code no longer compiled - the property is now called “column”. As I mentioned above, my strategy for dealing with this problem is to use version specific assemblies. Here is the Fluent NH solution:</p>
<p><a href="http://lh4.ggpht.com/_AP_-f1YlmB4/SbSqNLSPX5I/AAAAAAAAAOI/C0GAE1IwKYs/s1600-h/image%5B3%5D.png"><img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="125" alt="image" src="http://lh6.ggpht.com/_AP_-f1YlmB4/SbSqN8UizVI/AAAAAAAAAOM/4y1gC6Aame8/image_thumb%5B1%5D.png?imgmax=800" width="259" border="0"></a> </p>
<p>The two “Versioning” projects are where the version specific code goes – they each reference their own version of NHibernate. Each project contains the same set of extensions methods, each method implemented slightly differently depending on the versioning requirements. The two projects share the same namespace and output an assembly with the same name (FluentNHibernate.Versioning) and to the same location. Neither project is included in the default build configuration, so they have to be built explicitly. The act of building one of these versioning projects will make it “active” because the assembly is output to the same location that the FluentNHibernate project is referencing.</p>
<p>With the background out of the way, lets fix the problem with with “column1” property on HbmProperty. First I open the Versioning.NH20 project, find the HbmPropertyExtensions and add an extension method:</p><pre class="code"><span style="color: blue">public static class </span><span style="color: #2b91af">HbmPropertyExtensions
</span>{
...<br>
<span style="color: blue">public static void </span>SetColumn(<span style="color: blue">this </span><span style="color: #2b91af">HbmProperty </span>hbmProperty, <span style="color: blue">string </span>column)
{
hbmProperty.column1 = column;
}
}</pre>
<p>I then modify the code to call the extension method:</p><pre class="code"><span style="color: blue">if </span>(propertyMapping.Attributes.IsSpecified(x => x.ColumnName))
_hbm.SetColumn(propertyMapping.ColumnName);</pre>
<p>I compile the Versioning.NH20 project to make sure its active and run my tests. I already have a test that is verifying this implementation – here it is:</p><pre class="code">[<span style="color: #2b91af">Test</span>]
<span style="color: blue">public void </span>Should_write_the_attributes()
{
<span style="color: blue">var </span>testHelper = <span style="color: blue">new </span><span style="color: #2b91af">HbmTestHelper</span><<span style="color: #2b91af">PropertyMapping</span>>();
testHelper.Check(x => x.Name, <span style="color: #a31515">"test"</span>).MapsToAttribute(<span style="color: #a31515">"name"</span>);
testHelper.Check(x => x.Length, 50).MapsToAttribute(<span style="color: #a31515">"length"</span>);
testHelper.Check(x => x.IsNotNullable, <span style="color: blue">true</span>).MapsToAttribute(<span style="color: #a31515">"not-null"</span>);
testHelper.Check(x => x.ColumnName, <span style="color: #a31515">"thecolumn"</span>).MapsToAttribute(<span style="color: #a31515">"column"</span>); <font color="#ff0000"><strong><--- HERE</strong></font>
<span style="color: blue">var </span>writer = <span style="color: blue">new </span><span style="color: #2b91af">HbmPropertyWriter</span>();
testHelper.VerifyAll(writer);
}</pre><a href="http://11011.net/software/vspaste"></a>
<p>Because this test verifies that a certain property is written to the correct xml attribute, it works for both versions of NH. Regardless of what the property is called on the Hbm class, its written to the “column” attribute. </p>
<p>The tests all pass, so I switch to NH2.1 using my rake script and move to the Versioning.NH21 project. Again, I add an extension method:</p><pre class="code"><span style="color: blue">public static class </span><span style="color: #2b91af">HbmPropertyExtensions
</span>{
<span style="color: blue">...<br></span>
<span style="color: blue">public static void </span>SetColumn(<span style="color: blue">this </span><span style="color: #2b91af">HbmProperty </span>hbmProperty, <span style="color: blue">string </span>column)
{
hbmProperty.column = column;
}
}</pre>
<p>This looks almost the same as the code above, but notice that the “1” is gone. I compile the Versioning.NH21 project to make sure its active and run the tests. They all pass!</p>
<p>So far, all the versioning issues I’ve ran into were easily fixed like the one above. Lets hope they are all this simple!</p><pre class="code"> </pre><a href="http://11011.net/software/vspaste"></a> Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com4tag:blogger.com,1999:blog-882821950355432699.post-69042537315212418772009-02-21T17:09:00.000+11:002009-02-21T17:10:07.035+11:00Fluent NHibernate semantic model: Visitors<p>My work-in-progress semantic model based version of <a href="http://fluentnhibernate.org">Fluent NHibernate</a> makes heavy use of the <a href="http://en.wikipedia.org/wiki/Visitor_pattern">visitor pattern</a>. Currently, the visitor implementation is there to serve two purposes:</p> <ol> <li>Facilitate the construction of a Hbm* representation of the mapping model. Hbm* refers to the set of classes found in the NHibernate.Cfg.MappingSchema namespace that are generated from the NHibernate mapping schema. My version of Fluent NHibernate communicates with NHibernate by serializing the Hbm* representation to xml. </li> <li>Enable powerful, user-defined conventions that walk the mapping model and make changes. The NamingConvention class is a very simple example of this – it takes mapping model instances and sets their Name property based on reflected data such as the System.Type or the PropertyInfo. </li> </ol> <p>Lets begin by looking at the implementation of AcceptVisitor for the root of the mapping model – HibernateMapping:</p> <pre class="code"><span style="color: blue">public override void </span>AcceptVisitor(<span style="color: #2b91af">IMappingModelVisitor </span>visitor)
{
visitor.ProcessHibernateMapping(<span style="color: blue">this</span>);
<span style="color: blue">foreach </span>(<span style="color: blue">var </span>classMapping <span style="color: blue">in </span>Classes)
visitor.Visit(classMapping);
}</pre>
<p><a href="http://11011.net/software/vspaste"></a>This is reasonably straightforward. The HibernateMapping tells the visitor to first process a HibernateMapping instance, and passes itself as the argument. Then it tells the visitor to visit each of the child classes. What the visitor does when its told to visit a ClassMapping is its business, but what it is <em>likely</em> to do is call AcceptVisitor on the ClassMapping:</p>
<pre class="code"><span style="color: blue">public override void </span>AcceptVisitor(<span style="color: #2b91af">IMappingModelVisitor </span>visitor)
{
visitor.ProcessClass(<span style="color: blue">this</span>);
<span style="color: blue">if </span>(Id != <span style="color: blue">null</span>)
visitor.Visit(Id);
<span style="color: blue">if </span>(Discriminator != <span style="color: blue">null</span>)
visitor.Visit(Discriminator);
<span style="color: blue">foreach </span>(<span style="color: blue">var </span>subclass <span style="color: blue">in </span>Subclasses)
visitor.Visit(subclass);
<span style="color: blue">base</span>.AcceptVisitor(visitor);
}</pre>
<p><a href="http://11011.net/software/vspaste"></a>This is similar to the previous AcceptVisitor implementation, but its worth noting that at the end, it calls base.AcceptVisitor(visitor). This is necessary because ClassMapping inherits from a common base class (JoinedSubclassMapping and SubclassMapping also inherit from this base class). Here is AcceptVisitor on ClassMappingBase:</p>
<pre class="code"><span style="color: blue">public override void </span>AcceptVisitor(<span style="color: #2b91af">IMappingModelVisitor </span>visitor)
{
<span style="color: blue">foreach </span>(<span style="color: blue">var </span>collection <span style="color: blue">in </span>Collections)
visitor.Visit(collection);
<span style="color: blue">foreach </span>(<span style="color: blue">var </span>property <span style="color: blue">in </span>Properties)
visitor.Visit(property);
<span style="color: blue">foreach </span>(<span style="color: blue">var </span>reference <span style="color: blue">in </span>References)
visitor.Visit(reference);
}</pre>
<p><a href="http://11011.net/software/vspaste"></a>Of course – all class mappings, regardless of how they fit into an inheritance hierarchy, can have collections, properties and references (many-to-ones). Its probably not necessary to follow this any further. The important point is that as long as the visitor calls AcceptVisitor when it is told to visit something, then it will make its way along the entire mapping model. To make life easier, I’ve implemented a DefaultMappingModelVisitor class that does precisely this. It has a whole bunch of code that all looks very similar to this:</p>
<pre class="code"><span style="color: blue">public override void </span>Visit(<span style="color: #2b91af">PropertyMapping </span>propertyMapping)
{
propertyMapping.AcceptVisitor(<span style="color: blue">this</span>);
}
<span style="color: blue">public override void </span>Visit(<span style="color: #2b91af">ManyToOneMapping </span>manyToOneMapping)
{
manyToOneMapping.AcceptVisitor(<span style="color: blue">this</span>);
}
<span style="color: blue">public override void </span>Visit(<span style="color: #2b91af">KeyMapping </span>keyMapping)
{
keyMapping.AcceptVisitor(<span style="color: blue">this</span>);
}</pre>
<pre class="code">.. Many more Visit methods</pre>
<p><a href="http://11011.net/software/vspaste"></a>Now you might be looking at this and wondering why this is necessary. Why can’t we skip this completely, and just have AcceptVisitor implementations that will call AcceptVisitor directly like this:</p>
<pre class="code"><span style="color: blue">public override void </span>AcceptVisitor(<span style="color: #2b91af">IMappingModelVisitor </span>visitor)
{
visitor.ProcessHibernateMapping(<span style="color: blue">this</span>);
<span style="color: blue">foreach </span>(<span style="color: blue">var </span>classMapping <span style="color: blue">in </span>Classes)
classMapping.AcceptVisitor(visitor); <font color="#ff0000"><strong><--- JUST DO THIS??</strong></font>
}</pre>
<p>The answer is that the proposed change will work when you want one single visitor instance to visit the entire mapping model. While this works fine for conventions (as you will see in a moment), it does not work so well for building the Hbm representation. I’ll get to that in a second, but lets first take a look at the simpler case of the conventions. Here is a gutted version of the NamingConvention:</p>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">NamingConvention </span>: <span style="color: #2b91af">DefaultMappingModelVisitor
</span>{
<span style="color: blue">public </span><span style="color: #2b91af">Func</span><<span style="color: #2b91af">MemberInfo</span>, <span style="color: blue">string</span>> DetermineNameFromMember = info => info.Name;
<span style="color: blue">public </span><span style="color: #2b91af">Func</span><<span style="color: #2b91af">Type</span>, <span style="color: blue">string</span>> DetermineNameFromType = type => type.AssemblyQualifiedName;
<span style="color: blue">public override void </span>ProcessOneToMany(<span style="color: #2b91af">OneToManyMapping </span>oneToManyMapping)
{
<span style="color: blue">if </span>(!oneToManyMapping.Attributes.IsSpecified(x => x.ClassName))
{
<span style="color: blue">if </span>(oneToManyMapping.ChildType == <span style="color: blue">null</span>)
<span style="color: blue">throw new </span><span style="color: #2b91af">ConventionException</span>(<span style="color: #a31515">"Cannot apply the naming convention. No type specified."</span>, oneToManyMapping);
oneToManyMapping.ClassName = DetermineNameFromType(oneToManyMapping.ChildType);
}
}
}</pre>
<p>I’ve removed the majority of its implementation for the sake of brevity. As it currently stands, it will walk the entire mapping model (because it inherits from the aforementioned DefaultMappingModelVisitor), and when it encounters a OneToManyMapping, it will attempt to set its ClassName based on the ChildType property. Its worth noting that the full implementation of the NamingConvention class actually handles naming of many other mappings types, such as ClassMappings, ManyToManyMappings, etc. This means that this visitor completely handles the concern of setting the name of mapping model elements for the <em>entire</em> mapping model. This point is important, because the next example is different.  As I mentioned before, this visitor implementation would work fine with the previous simplification of having AcceptVisitor directly call AcceptVisitor on the children. Lets now move on to the process of building a Hbm* representation, and examine why the simplification won’t work so well for this case.</p>
<p>I define an interface for classes that build Hbm:</p>
<pre class="code"><span style="color: blue">public interface </span><span style="color: #2b91af">IHbmWriter</span><T>
{
<span style="color: blue">object </span>Write(T mappingModel);
} </pre>
<a href="http://11011.net/software/vspaste"></a>
<p>Here is an example implementor, a hbm writer that will handle ColumnMappings:</p>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">HbmColumnWriter </span>: <span style="color: #2b91af">NullMappingModelVisitor</span>, <span style="color: #2b91af">IHbmWriter</span><<span style="color: #2b91af">ColumnMapping</span>>
{
<span style="color: blue">private </span><span style="color: #2b91af">HbmColumn </span>_hbm;
<span style="color: blue">public object </span>Write(<span style="color: #2b91af">ColumnMapping </span>mappingModel)
{
_hbm = <span style="color: blue">null</span>;
mappingModel.AcceptVisitor(<span style="color: blue">this</span>);
<span style="color: blue">return </span>_hbm;
}
<span style="color: blue">public override void </span>ProcessColumn(<span style="color: #2b91af">ColumnMapping </span>columnMapping)
{
_hbm = <span style="color: blue">new </span><span style="color: #2b91af">HbmColumn</span>();
_hbm.name = columnMapping.Name;
<span style="color: blue">if</span>(columnMapping.Attributes.IsSpecified(x => x.IsNotNullable))
{
_hbm.notnull = columnMapping.IsNotNullable;
_hbm.notnullSpecified = <span style="color: blue">true</span>;
}
<span style="color: blue">if </span>(columnMapping.Attributes.IsSpecified(x => x.Length))
_hbm.length = columnMapping.Length.ToString();
<br /> //etc</pre>
<pre class="code"><span style="color: blue"></span> }
}</pre>
<p><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a>You’ll notice that this class inherits from NullMappingModelVisitor, which is basically a blank implementation of IMappingModelVisitor. It has all the methods, but none of them do anything. So this visitor ONLY knows how to handle ColumnMappings - if its passed to any other type of mapping, it will do nothing. This is certainly a difference approach to the NamingConvention, which actually knew how to set the name for Classes, OneToMany’s, ManyToMany’s and many other mapping model elements. So why does this difference exist? Basically, the job of generating all the Hbm that NHibernate requires is too big for one class. Creating separate classes for generating the appropriate HBM helps make the job more manageable. These classes can then be composed, like so:</p>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">HbmIdWriter </span>: <span style="color: #2b91af">NullMappingModelVisitor</span>, <span style="color: #2b91af">IHbmWriter</span><<span style="color: #2b91af">IdMapping</span>>
{
<span style="color: blue">private readonly </span><span style="color: #2b91af">IHbmWriter</span><<span style="color: #2b91af">ColumnMapping</span>> _columnWriter;
<span style="color: blue">private readonly </span><span style="color: #2b91af">IHbmWriter</span><<span style="color: #2b91af">IdGeneratorMapping</span>> _generatorWriter;
<span style="color: blue">private </span><span style="color: #2b91af">HbmId </span>_hbm;
<span style="color: blue">public </span>HbmIdWriter(<span style="color: #2b91af">IHbmWriter</span><<span style="color: #2b91af">ColumnMapping</span>> columnWriter, <span style="color: #2b91af">IHbmWriter</span><<span style="color: #2b91af">IdGeneratorMapping</span>> generatorWriter)
{
_columnWriter = columnWriter;
_generatorWriter = generatorWriter;
}
<span style="color: blue">public object </span>Write(<span style="color: #2b91af">IdMapping </span>mappingModel)
{
_hbm = <span style="color: blue">null</span>;
mappingModel.AcceptVisitor(<span style="color: blue">this</span>);
<span style="color: blue">return </span>_hbm;
}
<span style="color: blue">public override void </span>ProcessId(<span style="color: #2b91af">IdMapping </span>idMapping)
{
_hbm = <span style="color: blue">new </span><span style="color: #2b91af">HbmId</span>();
<span style="color: blue">if</span>(idMapping.Attributes.IsSpecified(x => x.Name))
_hbm.name = idMapping.Name;
}
<span style="color: blue">public override void </span>Visit(<span style="color: #2b91af">ColumnMapping </span>columnMapping)
{
<span style="color: blue">var </span>columnHbm = (<span style="color: #2b91af">HbmColumn</span>) _columnWriter.Write(columnMapping);
columnHbm.AddTo(<span style="color: blue">ref </span>_hbm.column);
}
<span style="color: blue">public override void </span>Visit(<span style="color: #2b91af">IdGeneratorMapping </span>generatorMapping)
{
<span style="color: blue">var </span>generatorHbm = (<span style="color: #2b91af">HbmGenerator</span>) _generatorWriter.Write(generatorMapping);
_hbm.generator = generatorHbm;
}
}</pre>
<p><a href="http://11011.net/software/vspaste"></a>This hbm writer handles IdMappings. IdMappings include one or more columns and a generator, so this writer composes a IHbmWriter<ColumnMapping> and a IHbmWriter<IdGeneratorMapping>. In this way, the task of creating the hbm representation can be managed by a <em>family</em> of visitors that delegate to each other as required.</p>
<p>Finally now, I can return to the previous point of why all the AcceptVisitor implementations call visitor.Visit(child) rather than child.AcceptVisitor(visitor). The former allows the current visitor to see that a <strong>different visitor</strong> is passed in when calling child.AcceptVisitor(). You can see some of this happening above, in the override for Visit(ColumnMapping) – it asks the IHbmWriter<ColumnMapping> to write the column. The implementation of that method will call columnMapping.AcceptVisitor(this). Thus, the Fluent NHibernate semantic model has an implementation of the visitor pattern that supports both single visitors that visit the entire graph themselves, and families of visitors that collaborate to get a large job done.</p> Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com2tag:blogger.com,1999:blog-882821950355432699.post-20633403144925275462009-02-08T16:34:00.000+11:002009-02-08T16:49:35.069+11:00Fluent NHibernate semantic model: AttributeStore<T><p>My <a href="http://fluent-nhibernate.googlecode.com/svn/branches/pb-rewrite/">work</a> to rewrite <a href="http://fluentnhibernate.org">Fluent NHibernate</a> using a semantic model continues at a reasonable pace. I will admit there is some unconventional stuff in the code base, and much of it deserves explanation. Today I would like to explain AttributeStore<T> - what it is for and how it works. Lets start by taking a look at the model class for the contents of a collection with OneToMany semantics:</p> <pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">OneToManyMapping </span>: <span style="color: #2b91af">MappingBase</span>, <span style="color: #2b91af">ICollectionContentsMapping
</span>{
<span style="color: blue">private readonly </span><span style="color: #2b91af">AttributeStore</span><<span style="color: #2b91af">OneToManyMapping</span>> _attributes;
<span style="color: blue">public </span>OneToManyMapping()
{
_attributes = <span style="color: blue">new </span><span style="color: #2b91af">AttributeStore</span><<span style="color: #2b91af">OneToManyMapping</span>>();
_attributes.SetDefault(x => x.ExceptionOnNotFound, <span style="color: blue">true</span>);
}
<span style="color: blue">public </span><span style="color: #2b91af">AttributeStore</span><<span style="color: #2b91af">OneToManyMapping</span>> Attributes
{
<span style="color: blue">get </span>{ <span style="color: blue">return </span>_attributes; }
}
<span style="color: blue">public string </span>ClassName
{
<span style="color: blue">get </span>{ <span style="color: blue">return </span>_attributes.Get(x => x.ClassName); }
<span style="color: blue">set </span>{ _attributes.Set(x => x.ClassName, <span style="color: blue">value</span>); }
}
<span style="color: blue">public bool </span>ExceptionOnNotFound
{
<span style="color: blue">get </span>{ <span style="color: blue">return </span>_attributes.Get(x => x.ExceptionOnNotFound); }
<span style="color: blue">set </span>{ _attributes.Set(x => x.ExceptionOnNotFound, <span style="color: blue">value</span>); }
}
}</pre>
<p>As you can see, I am doing something unusual in some of the getters and setters. Basically, I am storing the values of certain properties in a dictionary, and these values are keyed on the name of the property you use to access them. Its very easy to add new attributes, I use this Resharper live template:</p>
<pre class="code">public $ReturnType$ $PropertyName$
{
get { return $_attributes$.Get(x => x.$PropertyName$); }
set { $_attributes$.Set(x => x.$PropertyName$, value); }
}</pre>
<p>This approach allows me to write code that asks questions about properties beyond simply “what is the value?”. Here is an example from the NamingConvention class:</p>
<pre class="code"><span style="color: blue">public override void </span>ProcessOneToMany(<span style="color: #2b91af">OneToManyMapping </span>oneToManyMapping)
{
<span style="color: blue">if </span>(!oneToManyMapping.Attributes.IsSpecified(x => x.ClassName))
{
<span style="color: blue">if </span>(oneToManyMapping.ChildType == <span style="color: blue">null</span>)
<span style="color: blue">throw new </span><span style="color: #2b91af">ConventionException</span>(<span style="color: #a31515">"Cannot apply the naming convention. No type specified."</span>, oneToManyMapping);
oneToManyMapping.ClassName = DetermineNameFromType(oneToManyMapping.ChildType);
}
}</pre>
<a href="http://11011.net/software/vspaste"></a>This convention walks the mapping model, naming mappings based on the assigned Type or MemberInfo. In this example, if the ClassName property for the OneToManyMapping hasn’t been specified explicitly, then the NamingConvention uses the ChildType property to set the ClassName. If the user has set the ClassName themselves, then I don’t want the NamingConvention to overwrite that, so I ask the question “Is the ClassName property <strong>specified</strong>?”. If the ClassName property was just implemented as an autoproperty, I would probably have to check if it was null. But what if the property was a bool? Make it a nullable bool? Then I would have nasty if(blah.HasValue) code in various places. Yuck!
<p>Here is another example, this time from the class that creates a HbmOneToMany instance based on my OneToManyMapping:</p>
<pre class="code"><span style="color: blue">public override void </span>ProcessOneToMany(<span style="color: #2b91af">OneToManyMapping </span>oneToManyMapping)
{
_hbmOneToMany = <span style="color: blue">new </span><span style="color: #2b91af">HbmOneToMany</span>();
_hbmOneToMany.@class = oneToManyMapping.ClassName;
<span style="color: blue">if</span>(oneToManyMapping.Attributes.IsSpecified(x => x.ExceptionOnNotFound))
{
_hbmOneToMany.SetNotFound(oneToManyMapping.ExceptionOnNotFound);
}
}</pre>
<p><a href="http://11011.net/software/vspaste"></a>This code always sets the @class field on the HbmOneToMany, but it won’t always call SetNotFound. It only calls SetNotFound if the the ExceptionOnNotFound property was <strong>specified</strong>. The point of this behaviour is to only generate the xml the user desires. It is not mandatory to set the not-found attribute on a one-to-many element, so why write it if the user hasn’t specified it?</p>
<p>As well as being able to ask questions about the properties, I also wanted a convenient way to copy them. The next code sample is the code for OneToManyPart. This class is part of the fluent interface for FluentNHibernate. It builds up information on the collection being mapped, and builds the appropriate collection when ResolveCollectionMapping() is called (obviously the IsInverse property is the only value copied at the moment, but that will change as the supported functionality grows):</p>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">OneToManyPart</span><PARENT, CHILD> : <span style="color: #2b91af">IDeferredCollectionMapping
</span>{
<span style="color: blue">private readonly </span><span style="color: #2b91af">PropertyInfo </span>_info;
<span style="color: blue">private readonly </span><span style="color: #2b91af">AttributeStore</span><<span style="color: #2b91af">ICollectionMapping</span>> _attributes;
<span style="color: blue">private </span><span style="color: #2b91af">Func</span><<span style="color: #2b91af">ICollectionMapping</span>> _collectionBuilder;
<span style="color: blue">public </span>OneToManyPart(<span style="color: #2b91af">PropertyInfo </span>info)
{
_info = info;
_attributes = <span style="color: blue">new </span><span style="color: #2b91af">AttributeStore</span><<span style="color: #2b91af">ICollectionMapping</span>>();
AsBag();
}
<span style="color: blue">public </span><span style="color: #2b91af">OneToManyPart</span><PARENT, CHILD> AsBag()
{
_collectionBuilder = () => <span style="color: blue">new </span><span style="color: #2b91af">BagMapping</span>();
<span style="color: blue">return this</span>;
}
<span style="color: blue">public </span><span style="color: #2b91af">OneToManyPart</span><PARENT, CHILD> AsSet()
{
_collectionBuilder = () => <span style="color: blue">new </span><span style="color: #2b91af">SetMapping</span>();
<span style="color: blue">return this</span>;
}
<span style="color: blue">public </span><span style="color: #2b91af">OneToManyPart</span><PARENT, CHILD> IsInverse()
{
_attributes.Set(x => x.IsInverse, <span style="color: blue">true</span>);
<span style="color: blue">return this</span>;
}
<span style="color: #2b91af">ICollectionMapping IDeferredCollectionMapping</span>.ResolveCollectionMapping()
{
<span style="color: blue">var </span>collection = _collectionBuilder();
_attributes.CopyTo(collection.Attributes);
collection.PropertyInfo = _info;
collection.Key = <span style="color: blue">new </span><span style="color: #2b91af">KeyMapping</span>();
collection.Contents = <span style="color: blue">new </span><span style="color: #2b91af">OneToManyMapping </span>{ChildType = <span style="color: blue">typeof </span>(CHILD)};
<span style="color: blue">return </span>collection;
}
}</pre>
<p>The relevant lines are at the beginning of ResolveCollectionMapping(). Once the collection instance is created, the attributes collected in the _attributes field are copied to the AttributeStore for the new collection instance. </p>
<p>Well that is probably enough examples of why I am using this pattern. Now I want to run through the implementation. Lets start with AttributeStore<T>:</p>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">AttributeStore</span><T>
{
<span style="color: blue">private readonly </span><span style="color: #2b91af">AttributeStore </span>_store;
<span style="color: blue">public </span>AttributeStore()
: <span style="color: blue">this</span>(<span style="color: blue">new </span><span style="color: #2b91af">AttributeStore</span>())
{
}
<span style="color: blue">public </span>AttributeStore(<span style="color: #2b91af">AttributeStore </span>store)
{
_store = store;
}
<span style="color: blue">public </span>U Get<U>(<span style="color: #2b91af">Expression</span><<span style="color: #2b91af">Func</span><T, U>> exp)
{
<span style="color: blue">return </span>(U)(_store[GetKey(exp)] ?? <span style="color: blue">default</span>(U));
}
<span style="color: blue">public void </span>Set<U>(<span style="color: #2b91af">Expression</span><<span style="color: #2b91af">Func</span><T, U>> exp, U value)
{
_store[GetKey(exp)] = value;
}
<span style="color: blue">public void </span>SetDefault<U>(<span style="color: #2b91af">Expression</span><<span style="color: #2b91af">Func</span><T, U>> exp, U value)
{
_store.SetDefault(GetKey(exp), value);
}
<span style="color: blue">public bool </span>IsSpecified<U>(<span style="color: #2b91af">Expression</span><<span style="color: #2b91af">Func</span><T, U>> exp)
{
<span style="color: blue">return </span>_store.IsSpecified(GetKey(exp));
}
<span style="color: blue">public void </span>CopyTo(<span style="color: #2b91af">AttributeStore</span><T> target)
{
_store.CopyTo(target._store);
}
<span style="color: blue">private string </span>GetKey<U>(<span style="color: #2b91af">Expression</span><<span style="color: #2b91af">Func</span><T, U>> exp)
{
<span style="color: #2b91af">PropertyInfo </span>info = <span style="color: #2b91af">ReflectionHelper</span>.GetProperty(exp);
<span style="color: blue">return </span>info.Name;
}
}</pre>
<p><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a>As you can see, AttributeStore<T> is a generic wrapper for a non-generic class called AttributeStore. The purpose of AttributeStore<T> is to expose get and set methods that take a lambda, and convert that lambda into a dictionary key, and then delegate to an inner attribute store using that dictionary key. Finally, here is the code for the non-generic attribute store:</p>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">AttributeStore
</span>{
<span style="color: blue">private readonly </span><span style="color: #2b91af">IDictionary</span><<span style="color: blue">string</span>, <span style="color: blue">object</span>> _attributes;
<span style="color: blue">private readonly </span><span style="color: #2b91af">IDictionary</span><<span style="color: blue">string</span>, <span style="color: blue">object</span>> _defaults;
<span style="color: blue">public </span>AttributeStore()
{
_attributes = <span style="color: blue">new </span><span style="color: #2b91af">Dictionary</span><<span style="color: blue">string</span>, <span style="color: blue">object</span>>();
_defaults = <span style="color: blue">new </span><span style="color: #2b91af">Dictionary</span><<span style="color: blue">string</span>, <span style="color: blue">object</span>>();
}
<span style="color: blue">public object this</span>[<span style="color: blue">string </span>key]
{
<span style="color: blue">get
</span>{
<span style="color: blue">if </span>(_attributes.ContainsKey(key))
<span style="color: blue">return </span>_attributes[key];
<span style="color: blue">if </span>(_defaults.ContainsKey(key))
<span style="color: blue">return </span>_defaults[key];
<span style="color: blue">return null</span>;
}
<span style="color: blue">set </span>{ _attributes[key] = <span style="color: blue">value</span>; }
}
<span style="color: blue">public bool </span>IsSpecified(<span style="color: blue">string </span>key)
{
<span style="color: blue">return </span>_attributes.ContainsKey(key);
}
<span style="color: blue">public void </span>CopyTo(<span style="color: #2b91af">AttributeStore </span>store)
{
<span style="color: blue">foreach </span>(<span style="color: #2b91af">KeyValuePair</span><<span style="color: blue">string</span>, <span style="color: blue">object</span>> pair <span style="color: blue">in </span>_attributes)
store._attributes[pair.Key] = pair.Value;
}
<span style="color: blue">public void </span>SetDefault(<span style="color: blue">string </span>key, <span style="color: blue">object </span>value)
{
_defaults[key] = value;
}
}</pre>
<p><a href="http://11011.net/software/vspaste"></a>AttributeStore is just a wrapper for a couple of dictionaries, one for the values that have been specified, and one for the default values. That’s pretty much all there is to it. </p>
<p>I see AttributeStore<T> as a superior alternative to the weakly typed bag of attributes approach that Fluent NHibernate currently uses.There are no magic strings, and its all strongly typed. Its more powerful than just using properties with backing fields, and it requires pretty much the same amount of code. Sure, its much slower, but performance is not really a concern for Fluent NHibernate. I can see myself using this pattern on other projects.</p> Paulhttp://www.blogger.com/profile/18224234643439645641noreply@blogger.com0