<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3157881265969801285</id><updated>2012-02-28T22:08:46.607-08:00</updated><category term='Coding'/><category term='Rx'/><category term='Blend'/><category term='Software Tools'/><category term='Visual Studio'/><category term='Twitter'/><category term='CQRS'/><category term='IoC'/><category term='Logging'/><category term='Castle'/><category term='Source Control Management'/><category term='Lab49'/><category term='Forex'/><category term='Testing'/><title type='text'>BLing on Software Pragnitism</title><subtitle type='html'>striving for performance, elegance, simplicity</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>65</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-4363758329185830711</id><published>2011-10-31T15:45:00.001-07:00</published><updated>2011-10-31T18:11:20.458-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IoC'/><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><category scheme='http://www.blogger.com/atom/ns#' term='Lab49'/><title type='text'>My Thoughts on MEF</title><content type='html'>&lt;p&gt;Ever since MEF was conceived, despite the authors saying that it is &lt;strong&gt;not&lt;em&gt; &lt;/em&gt;&lt;/strong&gt;an IoC container, it has since evolved to become one of the more popular IoC containers.&amp;nbsp; I’ve always avoided it because I disagree with using attributes, and I’ve had no reason to use it over Autofac or Windsor.&lt;/p&gt; &lt;p&gt;Recently, I found a reason to use it – Metro-style applications only support MEF so far.&amp;nbsp; My Twitter client ping.pong uses Autofac as the IoC container.&amp;nbsp; It uses some very basic functionality like factories and hooks.&amp;nbsp; To my surprise, MEF has no support for either of these.&lt;/p&gt; &lt;p&gt;Coming across these limitations solidifies my opinion that MEF is a plugin container, not an IoC container.&lt;/p&gt; &lt;p&gt;First let’s take a look at automated factories. What I mean is that by registering Foo, like so:&lt;/p&gt; &lt;div id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;container.RegisterType&amp;lt;Foo&amp;gt;();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;the container will automatically provide us a Func&amp;lt;Foo&amp;gt; without explicitly having to register it. This can be useful when you want to create an instance of Foo some time in the future rather than at constructor time.&amp;nbsp; You can do this with MEF via an ExportFactory&amp;lt;T&amp;gt;, but it’s limited because you cannot override dependencies at resolve time.&lt;/p&gt;
&lt;p&gt;For example, let’s say Foo has a constructor of Foo(Bar1, Bar2, Bar3). With MEF, you have no control at resolution time what the Bars are. A container that has support for automated factories (like Autofac and Castle Windsor), will let you resolve a Func&amp;lt;Bar1, Foo&amp;gt;, which lets you override Bar1 at resolve time. Similarly, you can resolve a Func&amp;lt;Bar1, Bar2, Bar3, Foo&amp;gt; and override all dependencies. Any dependencies not overridden fall back to their configuration in the bootstrapper. This is a &lt;em&gt;very&lt;/em&gt; useful feature, and coupled with the scoping features for automatic disposal it opens up many doors for elegant solutions for what otherwise are complicated problems.&lt;/p&gt;
&lt;p&gt;On to the second point; MEF has limited extension points. This one sounds odd since MEF is all about designing decoupled plugins so surely it should have extension points! The problem here is that MEF is designed as an explicit API (attributes are required) rather than an implicit API. In Autofac, you can scan an assembly and register every type. In MEF, every class needs to have an [Export] on it.&amp;nbsp; It also baffles my mind why [ImportingConstructor] is required even when there’s only one constructor. All this explicitness means you lose a bunch of “free” extension points that typical IoC containers have, like this:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;b.RegisterAssemblyTypes(GetType().Assembly)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;  .OnActivated(x =&amp;gt; x.Context.Resolve&amp;lt;IEventAggregator&amp;gt;().Subscribe(x.Instance));&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;What the code above is saying that every time &lt;em&gt;any&lt;/em&gt; component is activated, it will subscribe to the event aggregator. If the component doesn’t IHandle&amp;lt;&amp;gt; any messages, it’s a no-op and continues on. If the instance does IHandle&amp;lt;&amp;gt; messages, this will ensure it’s hooked up.&lt;/p&gt;
&lt;p&gt;The closest thing I could find in MEF was IPartImportsSatisfiedNotification (yes, an interface, more explicitness!).&amp;nbsp; It contains a single method OnImportsSatisfied() which gets called when the part is created.&amp;nbsp; Needless to say, the one line of code from Autofac would translate into a method for every implementation of IHandle&amp;lt;&amp;gt;, and since OnImportsSatisfied() contains no contextual information, every component will need IEventAggregator injected just to be able to call Subscribe.&lt;/p&gt;
&lt;p&gt;To fully complete this example, Autofac has the following methods when registering a component: &lt;em&gt;OnRegistered, OnPreparing, OnActivating, OnActivated, &lt;/em&gt;and&lt;em&gt; OnRelease&lt;/em&gt;.&amp;nbsp; Each of these methods gives you complete contextual information at the time it is called like access to the current scope of the container, the instance (if applicable), which component which requested the dependency, etc.&amp;nbsp; This makes it almost too easy to extend the container.&lt;/p&gt;
&lt;p&gt;For MEF, the only real extension point is an ExportProvider.&amp;nbsp; It is pretty low level (all it does is parse attributes for you) so to write anything similar for MEF requires a lot more code.&amp;nbsp; To further illustrate this point, compare the interception modules from AutofacContrib and MefContrib.&amp;nbsp; The Autofac implementation is a single file with a couple extension methods.&amp;nbsp; The MEF implementation is an entire namespace, over multiple classes, not the mention that it also relies on other infrastructure code in MefContrib.&amp;nbsp; Basically, the guys that wrote MefContrib had to write a mini-container within MEF.&lt;/p&gt;
&lt;p&gt;MEF is great for building &lt;em&gt;&lt;strong&gt;extremely&lt;/strong&gt; loosely coupled &lt;/em&gt;applications.&amp;nbsp; I don’t think it has any business in an application where you know and own all of the dependencies; there are simply better libraries for that.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-4363758329185830711?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/4363758329185830711/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=4363758329185830711' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/4363758329185830711'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/4363758329185830711'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2011/10/my-thoughts-on-mef.html' title='My Thoughts on MEF'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-7173729561881131463</id><published>2011-10-09T10:32:00.001-07:00</published><updated>2011-10-10T19:03:17.117-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Twitter'/><title type='text'>ping.pong Twitter Client</title><content type='html'>&lt;p&gt;I have a whole &lt;a href="http://blingcode.blogspot.com/2011/09/push-driven-development-with-reactive.html"&gt;series&lt;/a&gt; dedicated to blogging about how I wrote a Twitter client from scratch, but if I want anyone to actually use it, I better do some advertising :-D.&lt;/p&gt; &lt;p&gt;ping.pong is a fast and lightweight Twitter client written in Silverlight.&amp;nbsp; As of this moment it targets v4 but will likely target v5 whenever that is released.&lt;/p&gt; &lt;p&gt;Here are some highlights…&lt;/p&gt; &lt;h3&gt;Visually Pleasing&lt;/h3&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-9wwcsDIu5Yg/TpHayG-NVXI/AAAAAAAAAHg/-Jo9iq0ghOA/image%25255B15%25255D.png?imgmax=800" width="377" height="280"&gt;&lt;/p&gt; &lt;p&gt;The UI is based on your typical column-based design.&amp;nbsp; The column widths will automatically resize to take up all available horizontal space.&amp;nbsp; There is no horizontal scrolling.&lt;/p&gt; &lt;h3&gt;&lt;strong&gt;Access to the Streaming API&lt;/strong&gt;&lt;/h3&gt; &lt;p&gt;No more rate limits!&amp;nbsp; Your timeline is connected directly with Twitter’s streaming API, which means whenever someone you follow tweets you will know about it in almost near real-time.&amp;nbsp; Searching is also done through the streaming API.&lt;/p&gt; &lt;h3&gt;Fast &amp;amp; Lightweight&lt;/h3&gt; &lt;p&gt;ping.pong was built to run fast with low CPU utilization.&amp;nbsp; Even when stream searching for “e” (yes, the letter E), the CPU usage stays under 15%.&amp;nbsp; The maximum number of tweets that Twitter sends appears to be 50 per second.&lt;/p&gt; &lt;h3&gt;Conversations&lt;/h3&gt; &lt;p&gt;ping.pong will quickly show an entire tweet conversation by navigating reply tags back to the original tweet that started it all.&lt;/p&gt; &lt;h3&gt;Free &amp;amp; Open Source&lt;/h3&gt; &lt;p&gt;The full source code for ping.pong can be found on &lt;a href="https://github.com/bling/Ping.Pong"&gt;GitHub&lt;/a&gt;.&amp;nbsp; You can compile it, make modifications as you please, and run it yourself.&amp;nbsp; The only thing missing is the consumer keys which uniquely identifies this client from another.&amp;nbsp; You can generate them through Twitter once you have a developer account.&lt;/p&gt; &lt;h3&gt;Installer&lt;/h3&gt; &lt;p&gt;The latest and greatest can be quickly installed from &lt;a href="http://dl.dropbox.com/u/2072014/Ping.Pong/PingPongTestPage.html"&gt;here&lt;/a&gt;.&amp;nbsp; Check back periodically for updates!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-7173729561881131463?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/7173729561881131463/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=7173729561881131463' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/7173729561881131463'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/7173729561881131463'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2011/10/pingpong-twitter-client.html' title='ping.pong Twitter Client'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/-9wwcsDIu5Yg/TpHayG-NVXI/AAAAAAAAAHg/-Jo9iq0ghOA/s72-c/image%25255B15%25255D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-3658586159535349540</id><published>2011-09-29T19:04:00.001-07:00</published><updated>2011-10-02T08:40:33.991-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Rx'/><category scheme='http://www.blogger.com/atom/ns#' term='Twitter'/><category scheme='http://www.blogger.com/atom/ns#' term='Lab49'/><title type='text'>Push Driven Development with Reactive Extensions</title><content type='html'>&lt;p&gt;&lt;br&gt;This is going to be the last post that concludes my series on building a real-time push app with Silverlight.&amp;nbsp; Any additional posts would likely be outside the context of writing a push app and more about how I’m adding features to ping.pong, my Twitter app, so I think this is a good place to wrap up and talk generally from a top down overview of building a push-style application.&lt;/p&gt; &lt;p&gt;Here’s a recap of everything discussed so far:&lt;/p&gt; &lt;p&gt;&lt;a href="http://blingcode.blogspot.com/2011/08/building-real-time-push-app-with.html"&gt;Part 1&lt;/a&gt;:&amp;nbsp; Basics – Creating an Observable around a basic HTTP web stream against Twitter’s streaming API&lt;/p&gt; &lt;p&gt;&lt;a href="http://blingcode.blogspot.com/2011/08/building-real-time-push-app-with_27.html"&gt;Part 2&lt;/a&gt;:&amp;nbsp; Subscription and Observation of Observables&lt;/p&gt; &lt;p&gt;&lt;a href="http://blingcode.blogspot.com/2011/08/building-real-time-push-app-with_28.html"&gt;Part 3&lt;/a&gt;:&amp;nbsp; Basics of UX design with a look at shadows and gradients.&lt;/p&gt; &lt;p&gt;&lt;a href="http://blingcode.blogspot.com/2011/09/building-real-time-push-app-with.html"&gt;Part 4&lt;/a&gt;:&amp;nbsp; Integrating with 3rd party libraries, notably Caliburn Micro and Linq2Twitter and how to achieve polling with observables.&lt;/p&gt; &lt;p&gt;&lt;a href="http://blingcode.blogspot.com/2011/09/building-real-time-push-app-with_08.html"&gt;Part 5&lt;/a&gt;:&amp;nbsp; A minor hick up with Linq2Twitter.&lt;/p&gt; &lt;p&gt;&lt;a href="http://blingcode.blogspot.com/2011/09/building-real-time-push-app-with_13.html"&gt;Part 6&lt;/a&gt;:&amp;nbsp; Taking advantage of transparencies to improve the design and reusability of UX.&lt;/p&gt; &lt;p&gt;&lt;a href="http://blingcode.blogspot.com/2011/09/building-real-time-push-app-with_16.html"&gt;Part 7&lt;/a&gt;:&amp;nbsp; A summary of all things encountered so far, replacing Linq2Twitter with Hammock, first release of code to &lt;a href="https://github.com/bling/Ping.Pong"&gt;GitHub&lt;/a&gt;, and a binary released capable pulling and streaming tweets from Twitter.&lt;/p&gt; &lt;p&gt;&lt;a href="http://blingcode.blogspot.com/2011/09/building-real-time-push-app-with_21.html"&gt;Part 8&lt;/a&gt;:&amp;nbsp; Examples of using Caliburn Micro to easily resolve data bindings that otherwise would be much more effort.&lt;/p&gt; &lt;p&gt;And that leads us to this post…&lt;/p&gt; &lt;h3&gt;PDD (Push Driven Development)&lt;/h3&gt; &lt;p&gt;One of the main goals of this series is to create a performant Silverlight app based on push principles, as opposed to more traditional pull principles.&amp;nbsp; To that effect, ping.pong has performed remarkably well and is limited only by Twitter’s throttling, which currently appears to be maximum of 50 tweets per second via the streaming API.&lt;/p&gt; &lt;p&gt;Writing the application from a push-driven mindset was definitely unintuitive at first, and I had to refactor (actually rewrite is more accurate) the code many times to move closer to a world where the application is simply &lt;em&gt;reacting&lt;/em&gt; to events thrown at it (as opposed to asking the world for events).&lt;/p&gt; &lt;p&gt;To be absolutely clear on what I mean on the differences between push and pull, here’s a comparison:&lt;/p&gt; &lt;table border="0" cellspacing="0" cellpadding="2" width="100%"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top"&gt;&lt;strong&gt;Pulling&lt;/strong&gt;&lt;/td&gt; &lt;td valign="top"&gt;&lt;strong&gt;Push&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="50%"&gt;var e = tweets.GetEnumerator();&lt;br&gt;while (e.MoveNext()) &lt;strong&gt;// is there more?&lt;br&gt;&lt;/strong&gt;{&lt;br&gt;&amp;nbsp; e.Current; &lt;strong&gt;// get current&lt;br&gt;&lt;/strong&gt;&amp;nbsp; DoSomething(e.Current);&lt;br&gt;}&lt;/td&gt; &lt;td valign="top" width="50%"&gt;IObservable&amp;lt;Data&amp;gt; data = /* get source */&lt;br&gt;&lt;br&gt;&lt;strong&gt;// whenever data comes, do something&lt;/strong&gt;&lt;br&gt;data.Subscribe(DoSometing); &lt;br&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;On the pulling side, the caller is much more concerned with the logic on how to process each message.&amp;nbsp; It needs to &lt;em&gt;repeatedly&lt;/em&gt; ask the world, “hey, is there more data?”.&lt;/p&gt; &lt;p&gt;On the push side, the caller merely asks the world, “hey, give me data when you get some”.&lt;/p&gt; &lt;p&gt;Twitter is a perfect example because their APIs have both a pulling and pushing models.&amp;nbsp; Traditional clients poll continuously all the time, and many had configurable options to try to stay under the 200 API calls per hour limit.&amp;nbsp; Most of Twitter’s API still consists of pulling, but the user’s home line and searching can be streamed in near real time via the streaming API, aka. push.&amp;nbsp; Streaming tweets effectively removes the API call limit.&lt;/p&gt; &lt;h3&gt;&lt;/h3&gt; &lt;h3&gt;Push and Pull with Reactive Extensions&lt;/h3&gt; &lt;p&gt;The beauty of Rx is that regardless of whether it is actually pushing or pulling, the API will look same:&lt;/p&gt; &lt;div id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;IObservable&amp;lt;Tweet&amp;gt; tweets = _client.GetHomeTimeline();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;tweets.Subscribe(t =&amp;gt; { &lt;span style="color: #008000"&gt;/* do something with the tweet */&lt;/span&gt; });&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;As far as the caller is concerned, it doesn’t care (or needs to know) whether the &lt;em&gt;GetHomeTimeline&lt;/em&gt; method is polling Twitter or streaming from Twitter.&amp;nbsp; All it needs to know is &lt;em&gt;when&lt;/em&gt; a tweet comes it will &lt;em&gt;react&lt;/em&gt; and do something in the Subscribe action.&lt;/p&gt;
&lt;p&gt;In fact, Subscribe simply means “when you have data, call this”, but that could also be immediately, which would be analogous to IEnumerable.&lt;/p&gt;
&lt;p&gt;However, if that was the only thing Rx provided it wouldn’t be as popular as it is, because other pub/sub solutions like the EventAggregator already provide a viable asynchronous solution.&lt;/p&gt;
&lt;p&gt;Unlocking Rx’s power comes with its multitude of operators.&amp;nbsp; Here’s an example:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; IObservable&amp;lt;Tweet&amp;gt; GetStreamingStatuses(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt; TwitterClient client)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;  &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; client.GetHomeTimeline()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;      .Merge(client.GetMentions())&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;      .Concat(client.GetStreamingHomeline());&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;GetHomeTimeline&lt;/em&gt; and &lt;em&gt;GetMentions&lt;/em&gt; initiate once-only pull style API calls, while &lt;em&gt;GetStreamingHomeline&lt;/em&gt; will initiate a sticky connection and stream subsequent tweets down the pipe.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;Merge&lt;/em&gt; operator is defined as this: “Merges an observable sequence of observable sequences into an observable sequence.”&lt;/p&gt;
&lt;p&gt;I think a better description would be “whenever there is data from any of the sources, push it through”.&amp;nbsp; In the example above, this would translate to whenever a tweet comes from either the home timeline or the mentions timeline, give me a Tweet (first-come-first-push), followed by anything from the streaming timeline.&lt;/p&gt;
&lt;p&gt;And there lies one of the greatest beauties of Rx.&amp;nbsp; &lt;em&gt;All&lt;/em&gt; of the complexity lies solely on setting up the stream and operators.&amp;nbsp; And that, also, is its disadvantage.&lt;/p&gt;
&lt;h3&gt;&lt;/h3&gt;
&lt;h3&gt;Rx Complexity&lt;/h3&gt;
&lt;p&gt;Let’s take a look at the &lt;em&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/hh212146(v=VS.103).aspx"&gt;Concat&lt;/a&gt;&lt;/em&gt; operator, defined as: “Concatenates two observable sequences.”&amp;nbsp; In the remarks sections it states this: “The Concat operator runs the first sequence to completion. Then, the second sequence is run to completion effectively concatenating the second sequence to the end of the first sequence.”&lt;/p&gt;
&lt;p&gt;Let’s try it out:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;var a = Observable.Interval(TimeSpan.FromSeconds(1)).Select(x =&amp;gt; x.ToString());&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;var b = Observable.Interval(TimeSpan.FromSeconds(1)).Select(x =&amp;gt; &lt;span style="color: #006080"&gt;"s"&lt;/span&gt; + x);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;a.Concat(b).Subscribe(Console.WriteLine);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;// output: 0, 1, 2, 3, 4...&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;As expected, only numbers are printed because the first sequence never ends, so it won’t concatenate the second one.&amp;nbsp; Let’s modify it so that it does finish:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; count = 0;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;var a = Observable.Interval(TimeSpan.FromSeconds(1))&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    .TakeWhile(_ =&amp;gt; ++count &amp;lt; 5)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    .Select(x =&amp;gt; x.ToString());&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Note, that using Observable.Generate is preferred because it doesn’t introduce an external variable, but I stuck with Interval so the code looks similar to the second observable.&amp;nbsp; As expected again, it will print “0, 1, 2, s0, s1, s2”.&lt;/p&gt;
&lt;p&gt;OK, let’s spice things up.&amp;nbsp; Let’s make &lt;em&gt;b&lt;/em&gt; a ConnectableObservable by using the &lt;em&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/hh229126(v=VS.103).aspx"&gt;Publish&lt;/a&gt;&lt;/em&gt; operator, and immediately call &lt;em&gt;Connect&lt;/em&gt;.&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; count = 0;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;var a = Observable.Interval(TimeSpan.FromSeconds(1))&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    .TakeWhile(_ =&amp;gt; ++count &amp;lt; 5)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    .Select(x =&amp;gt; x.ToString());&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;var b = Observable.Interval(TimeSpan.FromSeconds(1)).Select(_ =&amp;gt; &lt;span style="color: #006080"&gt;"s"&lt;/span&gt; + _).Publish();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;b.Connect();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;a.Concat(b).Subscribe(Console.WriteLine);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;What do you think the output of this will be?&amp;nbsp; The answer is “0, 1, 2, 3, &lt;strong&gt;s5, s6, s7&lt;/strong&gt;, …”&lt;/p&gt;
&lt;p&gt;Despite using the same &lt;em&gt;Concat&lt;/em&gt; operator, the result can be very different depending on the source observables.&amp;nbsp; If you use the &lt;em&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/hh229288(v=VS.103).aspx"&gt;Replay&lt;/a&gt;&lt;/em&gt; operator, it would have printed “0, 1, 2, 3, s0, s1, s2, …”&lt;/p&gt;
&lt;p&gt;Years and years of working in synchronous programming models have trained us to think in synchronous ways, and I picked Concat specifically because Concat also exists in the enumerable world.&amp;nbsp; Observable sequences are asynchronous, so we never know exactly &lt;em&gt;when&lt;/em&gt; data comes at us, only what to do when it does.&amp;nbsp; And because streams occur at different times, when you combine them together there are many many ways of doing so (CombineLatest, Merge, Zip, are just a few).&lt;/p&gt;
&lt;p&gt;The greatest hurdle to working in Rx is to know what the different combinations do.&amp;nbsp; This takes time and practice.&amp;nbsp; &lt;a href="http://mnajder.blogspot.com/2010/03/rxsandbox-v1.html"&gt;RxTools&lt;/a&gt; is a great learning tool to test out what all the operators do.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Unit Testing&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Last but not least, Rx can make it easier to write unit tests.&amp;nbsp; The concept is easy: take some inputs and test the output.&amp;nbsp; In practice this is complicated because applications typically carry a lot of state with them.&amp;nbsp; Even with dependency injection and mocking frameworks I’ve seen a lot of code where for every assert there is 10 lines of mock setup code.&lt;/p&gt;
&lt;p&gt;So how does it make it easier to test?&amp;nbsp; It reduces what you need to test to a single method, Subscribe, which takes one input, an IObservable&amp;lt;T&amp;gt;.&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Rx is a library unlike any other you will use.&amp;nbsp; With other libraries, you will add them to your solution, use a method here or there, and go on with your life.&amp;nbsp; With Rx, it will radically change the way you code and think in general.&amp;nbsp; It’s awesome.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-3658586159535349540?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/3658586159535349540/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=3658586159535349540' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/3658586159535349540'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/3658586159535349540'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2011/09/push-driven-development-with-reactive.html' title='Push Driven Development with Reactive Extensions'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-2810507767697103678</id><published>2011-09-21T20:25:00.001-07:00</published><updated>2011-09-21T20:25:15.065-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><category scheme='http://www.blogger.com/atom/ns#' term='Twitter'/><title type='text'>Building a Real-time Push App with Silverlight: Part 8</title><content type='html'>&lt;h3&gt;&amp;nbsp;&lt;/h3&gt; &lt;h3&gt;Exploring Caliburn Micro&lt;/h3&gt; &lt;p&gt;As I hinted in earlier posts, Caliburn Micro has some wicked conventions that makes for writing MVVM super easy, and it also have a very convenient syntax for hooking up events.&amp;nbsp; For example, the following:&lt;/p&gt; &lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Button&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Content&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="R"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;   &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;i:Interaction.Triggers&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;       &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;i:EventTrigger&lt;/span&gt; &lt;span style="color: #ff0000"&gt;EventName&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Click"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;           &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;i:InvokeCommandAction&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Command&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="{Binding ReplyCommand}"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;CommandParameter&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="{Binding}"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;       &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;i:EventTrigger&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;   &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;i:Interaction.Triggers&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Button&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Can be rewritten like this:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Button&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Content&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="R"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;cal:Message&lt;/span&gt;.&lt;span style="color: #ff0000"&gt;Attach&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="[Reply($dataContext)]"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;There are some smarts going on here.&amp;nbsp; Caliburn Micro will default to the Click event for buttons.&amp;nbsp; For a full syntax, it would be cal:Message.Attach=”[Event Click] = [Reply($dataContext)]”.&amp;nbsp; As you can imagine, that will call the Reply method and pass in the current data context.&amp;nbsp; You can also pass in other things like $this, $source, or $executionContext for full access to anything and everything Caliburn Micro itself has access to.&lt;/p&gt;
&lt;p&gt;The coolest thing about this is it gives you some wicked control over how your data context gets set.&amp;nbsp; Ever struggled with popup windows or data grids and using weird hacks to get the binding correct?&amp;nbsp; Caliburn Micro makes this very easy.&amp;nbsp; Here’s an example.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I have a DataTemplate which renders the UI for the model Tweet.&lt;/li&gt;
&lt;li&gt;Tweet is just a simple class which holds only properties.&lt;/li&gt;
&lt;li&gt;Inside the DataTemplate, I have some buttons that when the user clicks will reply, retweet, quote, or direct message.&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;The Tweet class is purely for modeling data, so adding any methods would be bad practice.&amp;nbsp; Also, since I’m in a DataTemplate I can’t easily reference another control with ElementName (in this case I need the containing parent’s DataContext).&amp;nbsp; And to add insult to injury, Silverlight 4 doesn’t have RelativeSource ancestor type.&amp;nbsp; So how do I solve this?&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;StackPanel&lt;/span&gt; &lt;span style="color: #ff0000"&gt;VerticalAlignment&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Bottom"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;cal:Action&lt;/span&gt;.&lt;span style="color: #ff0000"&gt;TargetWithoutContext&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="shell"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Orientation&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Horizontal"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Button&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Content&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="R"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;cal:Message&lt;/span&gt;.&lt;span style="color: #ff0000"&gt;Attach&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="[Reply($dataContext)]"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Button&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Content&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="RT"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;cal:Message&lt;/span&gt;.&lt;span style="color: #ff0000"&gt;Attach&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="[Retweet($dataContext)]"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Button&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Content&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Q"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;cal:Message&lt;/span&gt;.&lt;span style="color: #ff0000"&gt;Attach&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="[Quote($dataContext)]"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Button&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Content&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="DM"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;cal:Message&lt;/span&gt;.&lt;span style="color: #ff0000"&gt;Attach&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="[DirectMessage($dataContext)]"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;StackPanel&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The secret is the attached property TargetWithoutContext.&amp;nbsp; As the name implies, it will set the target for all the ActionMessages attached to all the buttons, without setting the context.&amp;nbsp; If I used the Target attached property, it would set all of the Buttons’ data context to the same object – not what we want.&amp;nbsp; Since the Button’s data context remains intact, we can call “Reply($dataContext)”, which calls the Reply method on the target object (set on the StackPanel) and pass in the Tweet.&amp;nbsp; “shell” is the key of the service that I registered into the container.&lt;/p&gt;
&lt;p&gt;Originally I wanted this entire series to be able writing a fast push data app with Silverlight and Rx, and now I’m finding that I’m writing an entire Twitter client because it’s so much fun :-).&lt;/p&gt;
&lt;p&gt;I’m going to make another release soon.&amp;nbsp; While the first release was merely experimental, the next one will be useful enough to potentially use full time.&amp;nbsp; As you can probably tell with this blog post, it supports all the actions mentioned previously (and it’ll appear on mouse hover):&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh3.ggpht.com/-glwUZLmbyns/Tnqql5gBCJI/AAAAAAAAAHI/e-PtgGCjy9Y/s1600-h/image%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-RIZG8I0_rik/TnqqmNCK-6I/AAAAAAAAAHM/-xU4_cj6iDg/image_thumb%25255B2%25255D.png?imgmax=800" width="319" height="85"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The tweet box is much improved and shows you how many character you have left:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh4.ggpht.com/-cGf_6wVWvPg/TnqqmTUoW9I/AAAAAAAAAHQ/HG2IM82v9sY/s1600-h/image%25255B7%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 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://lh4.ggpht.com/-2VhCjjYrcoo/TnqqmstbbUI/AAAAAAAAAHU/zK65JB2shQw/image_thumb%25255B3%25255D.png?imgmax=800" width="244" height="92"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And it’s smart enough to auto wrap http links via Twitter’s t.co service, and the counter takes that into account.&amp;nbsp; Some interesting things to note is that in the future &lt;em&gt;all links&lt;/em&gt; will be wrapped t.co.&amp;nbsp; Looks like Twitter is trying to eat up bt.ly or something.&lt;/p&gt;
&lt;p&gt;Clicking on @users and #topics will automatically open a new timeline and subscribe to those tweets.&amp;nbsp; It is almost full featured enough to become my main Twitter client.&amp;nbsp; There are certain features still missing, and it’s purely based on when I have time to port them over.&lt;/p&gt;
&lt;p&gt;As always, you can install directly from &lt;a href="http://dl.dropbox.com/u/2072014/Ping.Pong/PingPongTestPage.html"&gt;here&lt;/a&gt;, or you can grab the code on the &lt;a href="https://github.com/bling/Ping.Pong"&gt;GitHub&lt;/a&gt; page!&lt;/p&gt;
&lt;p&gt;Next post will be about Rx from a very top level perspective and how it influenced my code from beginning to be experienced and all refactorings in between.&amp;nbsp; Stay tuned!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-2810507767697103678?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/2810507767697103678/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=2810507767697103678' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/2810507767697103678'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/2810507767697103678'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2011/09/building-real-time-push-app-with_21.html' title='Building a Real-time Push App with Silverlight: Part 8'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/-RIZG8I0_rik/TnqqmNCK-6I/AAAAAAAAAHM/-xU4_cj6iDg/s72-c/image_thumb%25255B2%25255D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-8852821439507440025</id><published>2011-09-16T06:26:00.001-07:00</published><updated>2011-09-16T19:23:14.785-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Rx'/><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><category scheme='http://www.blogger.com/atom/ns#' term='Twitter'/><title type='text'>Building a Real-time Push App with Silverlight: Part 7</title><content type='html'>&lt;h3&gt;&lt;/h3&gt; &lt;h3&gt;Infrastructure Refactor&lt;/h3&gt; &lt;p&gt;A lot of things changed internally, and I mean….a lot….&lt;/p&gt; &lt;p&gt;From an infrastructure standpoint, I decided to remove the dependency on LinqToTwitter, and I replaced it with &lt;a href="https://github.com/danielcrenna/hammock"&gt;Hammock&lt;/a&gt;.&amp;nbsp; A couple things led me to this decision, one being the Silverlight support wasn’t as good as I’d hoped, and the streaming API implementation was limited.&amp;nbsp; After reading the Twitter documentation I realized that the REST API was super simple and I’d be better off writing a simple interface to it.&lt;/p&gt; &lt;p&gt;I heard good things about Hammock, so I decided to give that one a try (I wasn’t going to go as far as reimplementing OAuth).&amp;nbsp; It was pretty easy to set up and in the end I was able to get Twitter working again and with less lines of code compared to the beginning of the refactor.&lt;/p&gt; &lt;h3&gt;Goals&lt;/h3&gt; &lt;p&gt;I had a couple goals for this project:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;Learn:&lt;/strong&gt;&amp;nbsp; I was a complete newbie to Reactive Extensions when I started but now I understand it enough to hit the ground running with it.&amp;nbsp; I’m still learning about more conventions available to Caliburn.Micro.  &lt;li&gt;&lt;strong&gt;UX:&lt;/strong&gt;&amp;nbsp; I wanted to learn a little more about interface design.&amp;nbsp; I wanted to know how little changes to gradients, shadows, colors, etc. could have a radically effect in the end result.  &lt;li&gt;&lt;strong&gt;Performance:&lt;/strong&gt;&amp;nbsp; It should be fast.&amp;nbsp; It should be able to react to real-time data.&amp;nbsp; And it should do it with low CPU utilization.  &lt;li&gt;&lt;strong&gt;Concise:&lt;/strong&gt;&amp;nbsp; I am a huge advocate for KISS.&amp;nbsp; I like convention over configuration.&amp;nbsp; I like implementing something in 2 lines of code rather than 20 (assuming it’s not cryptic).&amp;nbsp; As I was writing the app and refactoring, if there was an opportunity to remove a line of code, I did it.&amp;nbsp; The result is that the app currently consists of less than 500 lines of code as of this post (excluding XAML).&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;Tidbits&lt;/h3&gt; &lt;p&gt;What are some interest things I learned?&lt;/p&gt; &lt;ul&gt; &lt;li&gt;System.Json is an amazing assembly.&amp;nbsp; All you need to do is invoke JsonValue.Parse on a string and it will create a JsonValue for you, which will be a dictionary of key/value pairs.&amp;nbsp; What’s more, by doing something like “string s = json[“text”]” will do an explicit conversion &lt;strong&gt;and unescape JSON characters&lt;/strong&gt;, and &lt;strong&gt;only&lt;/strong&gt; via the explicit operator.&amp;nbsp; Calling ToString(), even though converting it to a string, will not unescape.&amp;nbsp; This was completely undocumented and only found when I looked at the source code via Resharper’s external sources feature.  &lt;li&gt;Rx is awesome.&amp;nbsp; When I ran into performance problems of trying to stream tweets from the world that contained the letter ‘a’ all I had to do was add an operator to improve the performance (in this case it was Buffer).&amp;nbsp; It should be noted that it is &lt;em&gt;very important&lt;/em&gt; to understand what Rx is doing underneath the hood to realize its benefits.&amp;nbsp; Rx lets you refactor 30 lines of async code into 1 operator, but it’s still doing that 30 lines of code – you just don’t see it.  &lt;li&gt;I really, &lt;em&gt;really&lt;/em&gt;, like the conventions available from Caliburn.&amp;nbsp; Some of the features that come out of the box from this very small library saves me from writing a lot of boilerplate code like commands, triggers, and evening bindings (Caliburn will auto bind x:Name to a property).  &lt;li&gt;Twitter’s documentation for &lt;a href="https://dev.twitter.com/docs/streaming-api/user-streams"&gt;user streams&lt;/a&gt; currently sucks and some trial and error was required to get it working.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;What is the end result of all this effort?&amp;nbsp; We have a styled Twitter app that can update your status, pull your home/mentions timeline, and most importantly will &lt;strong&gt;stream all subsequent tweets&lt;/strong&gt;.&amp;nbsp; There’s no pulling and no limits.&amp;nbsp; You will get a tweet of everyone you follow in real-time as it happens.&lt;/p&gt; &lt;p&gt;Moreover, there’s a feature to connect to the Streaming API to search Twitter for &lt;em&gt;anything&lt;/em&gt;.&amp;nbsp; To get an idea of what we’re talking about, here’s a full screenshot of it:&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-tB6iLGL85aE/TnNOi7hdq9I/AAAAAAAAAHE/wGjkyHQzYKs/image%25255B20%25255D.png?imgmax=800" width="578" height="328"&gt;&lt;/p&gt; &lt;p&gt;You read that right.&amp;nbsp; I’m streaming any tweet in the world that has the words ‘and’, ‘the’, ‘yes’, &lt;strong&gt;or&lt;/strong&gt; ‘no’ in them.&amp;nbsp; This is streaming around 400kB/s continuously and CPU utilization is under 25%.&amp;nbsp; The tweets are coming so fast it’s impossible to read them (at a rate of 50 tweets/second), so ideally you’d want to specify realistic search terms.&lt;/p&gt; &lt;p&gt;Moreover, the majority of the performance cost is actually downloading all the profile images.&amp;nbsp; If I take took out pictures I could stream any tweet in the world that has the letter ‘e’ in it at under 10% CPU.&amp;nbsp; It looks like Twitter limits the rate of tweets to 50 tweets/second because that was the rate for this one as well.&lt;/p&gt; &lt;p&gt;Features are minimalistic.&amp;nbsp; You can update your status, but you can’t DM, you can’t RT, you can’t do any of the normal things.&amp;nbsp; My original goal was not to write another Twitter client, but it’s actually quite fun to do so, so I’ll probably eventually get all features in.&lt;/p&gt; &lt;p&gt;And as promised, it’s up on &lt;a href="https://github.com/bling/Ping.Pong"&gt;GitHub&lt;/a&gt;, and version 0.0.0.1 &lt;strong&gt;alpha&lt;/strong&gt; (yes! expect bugs!!) is available in the downloads section.&amp;nbsp; Or, here’s a direct link to the XAP file on my &lt;a href="http://dl.dropbox.com/u/2072014/Ping.Pong/PingPongTestPage.html"&gt;Dropbox&lt;/a&gt;.&amp;nbsp; Have fun!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-8852821439507440025?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/8852821439507440025/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=8852821439507440025' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/8852821439507440025'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/8852821439507440025'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2011/09/building-real-time-push-app-with_16.html' title='Building a Real-time Push App with Silverlight: Part 7'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/-tB6iLGL85aE/TnNOi7hdq9I/AAAAAAAAAHE/wGjkyHQzYKs/s72-c/image%25255B20%25255D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-8160371184354791579</id><published>2011-09-13T07:00:00.000-07:00</published><updated>2011-09-13T07:00:13.951-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Twitter'/><category scheme='http://www.blogger.com/atom/ns#' term='Blend'/><title type='text'>Building a Real-time Push App with Silverlight: Part 6</title><content type='html'>&lt;p&gt;Back to the UI!&lt;/p&gt; &lt;p&gt;For this post I’m going to restyle the tweets.&amp;nbsp; Recall that they currently look like this:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-8dwHklIFVZU/Tm7ibyiDZFI/AAAAAAAAAGk/qJnwiFOB8f0/s1600-h/image4.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-ooxWWcVmX9w/Tm7icHgdN_I/AAAAAAAAAGo/wQ3qnvYAeWw/image_thumb2.png?imgmax=800" width="313" height="83"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The gradient background is currently #FFEEEEEE to #FFDDDDDD.&amp;nbsp; For this post I’m going to talk about a very powerful tool in a designer’s arsenal: &lt;em&gt;transparency&lt;/em&gt;.&lt;/p&gt; &lt;p&gt;Your first may be to think “big deal”, but just like programmers can use base classes and injection to share common code, designers can use transparency to achieve a similar effect.&lt;/p&gt; &lt;p&gt;Let’s change change the color to be black, and tweak only the alpha.&amp;nbsp; I’m going to set the colors to be #11000000 to #22000000 on a white background.&amp;nbsp; This is the result:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-JEP92O5RoSY/Tm7icVNyd4I/AAAAAAAAAGs/l6-KdEzjCYQ/s1600-h/image9.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-Ev-xA7pMsak/Tm7icnmllQI/AAAAAAAAAGw/xMZM3yNsGZA/image_thumb5.png?imgmax=800" width="313" height="83"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Looks almost identical doesn’t it?&amp;nbsp; However, by doing this we have dramatically improved the reusability of the gradient.&amp;nbsp; Here’s what happens when I change the background to be a different color:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-XOqa5ur3DBQ/Tm7iciocdYI/AAAAAAAAAG0/6SNKx6PSN3w/s1600-h/image14.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-uPxkKsog7xU/Tm7ic2vJhpI/AAAAAAAAAG4/J-PMDfe_6EM/image_thumb8.png?imgmax=800" width="313" height="83"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;I just changed one variable to do that.&amp;nbsp; If I wanted to provide different themes for my application it would be &lt;em&gt;extremely&lt;/em&gt; easy to do that if all the data templates were built with transparencies.&amp;nbsp; In fact, I just slap on a ColorPicker and I’d be done!&lt;/p&gt; &lt;p&gt;Even though it’d be easy to do this, any application that is dominated by one color gets boring very quickly. Most applications that look nice tend to focus around two dominant colors that contrast well against each other. Black and white are very common because they contrast well with a large variety of colors, but you can also have things like blue/green, purple/orange, etc.&amp;nbsp; As always, as long as you’re consistent you’ll likely have a good result.&lt;/p&gt; &lt;p&gt;Now, the flip side of the equation is also possible.&amp;nbsp; This is where you have something that exists already and then you put a transparent layer on top of it, creating a lightening or dimming effect.&amp;nbsp; In my experience I’ve found this to be inferior because it tends to wash out colors.&amp;nbsp; In the example above, if I applied a slightly transparent layer over top of the tweet, my picture and text would be negatively affected.&amp;nbsp; This is nonetheless a very useful trick, like with mouse over effects where you want a quick and cheap way of conveying information to the user.&lt;/p&gt; &lt;p&gt;Now, let’s take a big detour and restyle the entire application and go with a completely different theme.&amp;nbsp; I also wanted try something besides Apple and Microsoft inspired designs, which was more difficult than expected because I guess I’m not as creative as I thought I was :-).&amp;nbsp; Coming up with a good design takes a long time, and frequently you need some sort of inspiration.&amp;nbsp; Twitter in general is a very simple application, so the best designs are simple as well.&lt;/p&gt; &lt;p&gt;In an attempt to try to come up with something “cool” and “unique”, I started with the idea of elevated boxes layered on top of each other.&amp;nbsp; Here’s a before and after once I was done:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-s_ruhKWRmL0/Tm7idDwxdsI/AAAAAAAAAG8/XE18TaWC600/s1600-h/image20.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-Mz_J4B2JDLM/Tm7idcOBx-I/AAAAAAAAAHA/7FGeCgmZzek/image_thumb11.png?imgmax=800" width="625" height="303"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The redesign went through many iterations.&amp;nbsp; I showed it to friends and colleagues and got mixed feelings.&amp;nbsp; Some liked it.&amp;nbsp; Some thought it was too noisy.&amp;nbsp; And herein revealed a problem with complex designs – they are hard to get right!&amp;nbsp; That, and they tend to divide audience into those that really like it, and those that really don’t.&lt;/p&gt; &lt;p&gt;Anyways, the beauty of XAML is that I can try something else entirely without any changes to the code, so I’ll try another theme in the future.&lt;/p&gt; &lt;p&gt;I’m about 90% ready to release code to GitHub along with the first public alpha version.&amp;nbsp; Stay tuned!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-8160371184354791579?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/8160371184354791579/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=8160371184354791579' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/8160371184354791579'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/8160371184354791579'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2011/09/building-real-time-push-app-with_13.html' title='Building a Real-time Push App with Silverlight: Part 6'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/-ooxWWcVmX9w/Tm7icHgdN_I/AAAAAAAAAGo/wQ3qnvYAeWw/s72-c/image_thumb2.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-1262037256093707829</id><published>2011-09-08T18:26:00.001-07:00</published><updated>2011-09-10T07:10:03.540-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><category scheme='http://www.blogger.com/atom/ns#' term='Twitter'/><title type='text'>Building a Real-time Push App with Silverlight: Part 5</title><content type='html'>&lt;p&gt;I planned on this post to be about UI, but I’m going to defer that until the next post.&amp;nbsp; I said from the start of this series that I would document about everything about building the application from scratch, including my struggles.&lt;/p&gt; &lt;p&gt;And with that I want to mention something that got me scratching my head one too many times.&amp;nbsp; It was with how I used LinqToTwitter.&amp;nbsp; Here is the source code which you can immediately copy/paste into a blank project to reproduce:&lt;/p&gt; &lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;partial&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; MainPage : UserControl&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;    &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; TwitterContext _context = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; TwitterContext();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;    &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; ViewModel _vm1, _vm2, _vm3;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; MainPage()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;    {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;        InitializeComponent();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;        _vm1 = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ViewModel(_context);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;        _vm2 = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ViewModel(_context);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;        _vm3 = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ViewModel(_context);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;        _vm1.Callback += () =&amp;gt; Debug.WriteLine(&lt;span style="color: #006080"&gt;"Callback of VM1: "&lt;/span&gt; + _vm1.LocalState);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;        _vm2.Callback += () =&amp;gt; Debug.WriteLine(&lt;span style="color: #006080"&gt;"Callback of VM2: "&lt;/span&gt; + _vm2.LocalState);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;        _vm3.Callback += () =&amp;gt; Debug.WriteLine(&lt;span style="color: #006080"&gt;"Callback of VM3: "&lt;/span&gt; + _vm3.LocalState);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;        _vm1.Start();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;        _vm2.Start();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;        _vm3.Start();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;    }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ViewModel&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt; {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum24"&gt;  24:&lt;/span&gt;    &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; TwitterContext _context;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum25"&gt;  25:&lt;/span&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;event&lt;/span&gt; Action Callback;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum26"&gt;  26:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum27"&gt;  27:&lt;/span&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; LocalState;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum28"&gt;  28:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum29"&gt;  29:&lt;/span&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ViewModel(TwitterContext context)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum30"&gt;  30:&lt;/span&gt;    {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum31"&gt;  31:&lt;/span&gt;        _context = context;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum32"&gt;  32:&lt;/span&gt;    }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum33"&gt;  33:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum34"&gt;  34:&lt;/span&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Start()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum35"&gt;  35:&lt;/span&gt;    {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum36"&gt;  36:&lt;/span&gt;        var query = (from s &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; _context.Status&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum37"&gt;  37:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;where&lt;/span&gt; s.Type == StatusType.Public &amp;amp;&amp;amp; s.Count == 10&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum38"&gt;  38:&lt;/span&gt;                     select s);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum39"&gt;  39:&lt;/span&gt;        Debug.WriteLine(&lt;span style="color: #006080"&gt;"Hash code of ViewModel: "&lt;/span&gt; + query.GetHashCode());&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum40"&gt;  40:&lt;/span&gt;        query.AsyncCallback(statuses =&amp;gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum41"&gt;  41:&lt;/span&gt;        {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum42"&gt;  42:&lt;/span&gt;            LocalState++;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum43"&gt;  43:&lt;/span&gt;            Debug.WriteLine(&lt;span style="color: #006080"&gt;"Hash code inside callback: "&lt;/span&gt; + GetHashCode());&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum44"&gt;  44:&lt;/span&gt;            Callback();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum45"&gt;  45:&lt;/span&gt;        }).FirstOrDefault();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum46"&gt;  46:&lt;/span&gt;    }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum47"&gt;  47:&lt;/span&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Now, if you run this, you will see that only &lt;strong&gt;one&lt;/strong&gt; of the view models will get its state updated.&amp;nbsp; Huh?!&lt;/p&gt;
&lt;p&gt;How is that possible?&amp;nbsp; I started getting paranoid so I even added the local state variable “just in case.”&lt;/p&gt;
&lt;p&gt;Well, I had to look into the source code of LinqToTwitter to figure out exactly what happened.&amp;nbsp; Here is the code for AsyncCallback:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; IQueryable&amp;lt;T&amp;gt; AsyncCallback&amp;lt;T&amp;gt;(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt; IQueryable&amp;lt;T&amp;gt; queryType, Action&amp;lt;IEnumerable&amp;lt;T&amp;gt;&amp;gt; callback)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt; {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;     (queryType.Provider &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; TwitterQueryProvider)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;         .Context&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;         .TwitterExecutor&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;         .AsyncCallback = callback;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; queryType;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;See what happened?&amp;nbsp; The callback gets overwritten every time you call this method.&amp;nbsp; Even though the call to &lt;em&gt;FirstOrDefault&lt;/em&gt;() causes all 3 expressions to evaluate, only the last view model will get values because that’s the with the callback attached.&lt;/p&gt;
&lt;p&gt;Lesson of the day: The AsyncCallback extension method for LinqToTwitter is not thread-safe.&lt;/p&gt;
&lt;p&gt;So…the question is, how do we make it thread safe?&amp;nbsp; I just replaced wrapped the AsyncCallback with another extension method:&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; AutoResetEvent _twitterEvt = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; AutoResetEvent(&lt;span style="color: #0000ff"&gt;true&lt;/span&gt;);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; AsyncTwitterCallback&amp;lt;T&amp;gt;(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt; IQueryable&amp;lt;T&amp;gt; twitter, Action&amp;lt;IEnumerable&amp;lt;T&amp;gt;&amp;gt; callback)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    Observable.Start(() =&amp;gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        _twitterEvt.WaitOne();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        twitter.AsyncCallback(results =&amp;gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            &lt;span style="color: #0000ff"&gt;try&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                callback(results);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            &lt;span style="color: #0000ff"&gt;finally&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                _twitterEvt.Set();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        }).FirstOrDefault();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    });&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;Nothing complicated – just a simple wait handle to ensure only 1 thread can go through at a time.
&lt;p&gt;Hopefully upstream fixes this, or at least documents it.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-1262037256093707829?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/1262037256093707829/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=1262037256093707829' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/1262037256093707829'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/1262037256093707829'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2011/09/building-real-time-push-app-with_08.html' title='Building a Real-time Push App with Silverlight: Part 5'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-4334702627781245436</id><published>2011-09-05T14:26:00.001-07:00</published><updated>2011-09-05T14:49:50.244-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Rx'/><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><category scheme='http://www.blogger.com/atom/ns#' term='Twitter'/><title type='text'>Building a Real-time Push App with Silverlight: Part 4</title><content type='html'>&lt;p&gt;Originally I wanted to avoid bringing in external libraries to keep the app as lean as possible, but then I realized that I would spend too much time reinventing the wheel.&amp;nbsp; Twitter is deprecating basic authentication in the near future, which makes OAuth no longer optional.&amp;nbsp; Rather than writing yet another Twitter client (if you’re curious I found a great reference &lt;a href="http://chris.59north.com/post/2009/09/16/SilverTweet-e28093-Building-a-Silverlight-Twitter-client-part-1.aspx"&gt;here&lt;/a&gt;), I fired up &lt;a href="http://nuget.org/"&gt;NuGet&lt;/a&gt; and brought in &lt;a href="http://linqtotwitter.codeplex.com/"&gt;LinqToTwitter&lt;/a&gt;, and while I’m there I brought in &lt;a href="http://code.google.com/p/autofac/"&gt;Autofac&lt;/a&gt; and &lt;a href="http://caliburnmicro.codeplex.com/"&gt;Caliburn.Micro&lt;/a&gt; as well.&lt;/p&gt; &lt;p&gt;Naturally, LinqToTwitter will work nicely with Rx because as name implies it uses LINQ heavily.&amp;nbsp; Caliburn.Micro is a MVVM library which I’ve always wanted an excuse to try because of features like this:&lt;/p&gt; &lt;div id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;ListBox&lt;/span&gt; &lt;span style="color: #ff0000"&gt;cal:Message&lt;/span&gt;.&lt;span style="color: #ff0000"&gt;Attach&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="[Event Loaded] = [LoadList($dataContext)]"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;That’s only scratching the surface of what Caliburn can do, so it will be a fresh breath of air to see what else it can do.&lt;/p&gt;
&lt;p&gt;By default, Caliburn uses MEF to wire up its bootstrapper.&amp;nbsp; After adding a couple [Import]s and [Export]s, I knew it wasn’t for me.&amp;nbsp; It works well for writing plugins, i.e. &lt;em&gt;external&lt;/em&gt; dependencies because of its built-in assembly scanning capabilities, but for injecting &lt;em&gt;internal&lt;/em&gt; dependencies, other IoC containers do a much better job of that.&amp;nbsp; I used Castle Windsor in past projects, but for a change I’m going to use Autofac which I haven’t used since v2 came out.&lt;/p&gt;
&lt;p&gt;When this was all said and done the View was the only thing that didn’t change.&amp;nbsp; Everything underneath either changed radically or was deleted altogether (because LinqToTwitter provided it).&amp;nbsp; I added OAuth support and registered my application with Twitter, and with that was the birth of Ping Pong.&lt;/p&gt;
&lt;p&gt;This took much longer than expected.&amp;nbsp; Silverlight 5 RC just came out and it broke pretty much any container (including MEF) for OOB because of a TypeLoadException.&amp;nbsp; I haven’t been using too many v5 features, so for the time being I downgraded to v4 to get the project working until RC2 comes out.&lt;/p&gt;
&lt;p&gt;Integrating LinqToTwitter was a challenge.&amp;nbsp; The project site has a lot of good documentation, but most of it was for desktop, not Silverlight, and because of that I banged my head a couple times.&amp;nbsp; I wish I grabbed the source code earlier because it’s there where you’ll find hundreds of working examples (in code!) to do everything with the library (and in Silverlight).&lt;/p&gt;
&lt;p&gt;After all that, PingPong now has 3 columns (home, public, sampling) that &lt;em&gt;dynamically resizes&lt;/em&gt; (it’s surprising that &lt;a href="http://metrotwit.com"&gt;MetroTwit&lt;/a&gt; is the only client that does this….) to the window size.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh3.ggpht.com/-Upxh69yDp78/TmU-eu-P5tI/AAAAAAAAAGY/P3E3TP6sjfk/s1600-h/image%25255B23%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-f1uQ63FwyoI/TmU-fK3WfQI/AAAAAAAAAGc/Y26EvwnXy_4/image_thumb%25255B15%25255D.png?imgmax=800" width="554" height="413"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Oh, and there’s pictures now!&amp;nbsp; The streaming time line takes significantly more CPU now that it has to load images, but we’re still sitting at around 5-10% for what is continuously streaming data and loading pictures.&amp;nbsp; Not too shabby!&amp;nbsp; (It took a couple tries to get a PG-13 screenshot from the public/streaming time lines…)&lt;/p&gt;
&lt;p&gt;To conclude this post in the series, I’m going to talk about converting an asynchronous operation into an Observable that does not follow any predefined pattern.&lt;/p&gt;
&lt;h2&gt;Creating an Observable&lt;/h2&gt;
&lt;p&gt;One of Silverlight’s limitations is that almost everything needs to be an asynchronous call.&amp;nbsp; In regards to LinqToTwitter, something like this will fail (but work on desktop):&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;var tweets = (from t &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; context.Status&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;              &lt;span style="color: #0000ff"&gt;where&lt;/span&gt; t.Type == StatusType.Public&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;              select t).ToArray();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;On Silverlight you will get a single empty element.&amp;nbsp; To get it working, there is an extension method that comes with the library, and you use it like this:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;(from t &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; context.Status&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt; &lt;span style="color: #0000ff"&gt;where&lt;/span&gt; t.Type == StatusType.Public&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt; select t)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;  .AsyncCallback(tweets =&amp;gt; { &lt;span style="color: #008000"&gt;/* do something with it */&lt;/span&gt; })&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;  .FirstOrDefault();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Code is self-explanatory.&amp;nbsp; The FirstOrDefault() exists only to initiate the expression, otherwise it wouldn’t do anything.&amp;nbsp; So now the question is how do we convert that into an Rx Observable?&lt;/p&gt;
&lt;p&gt;Every time I write an Rx query I try to use the least amount of state as possible.&amp;nbsp; This helps to keep the number unexpected anomalies to a minimum.&amp;nbsp; In the following section of code, I was able to get it down to 2 fields: _sinceId, and Context.&amp;nbsp; There is probably some operator that will let me save the sinceId variable from one observable to the next but I wasn’t able to figure it out.&amp;nbsp; In any case, I came up with this:&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;_subscription =&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    Observable.Create&amp;lt;Tweet&amp;gt;(&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        ob =&amp;gt; Observable.Interval(TimeSpan.FromSeconds(60))&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                  .StartWith(-1)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                  .SubscribeOnThreadPool()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                  .Subscribe(_ =&amp;gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                  {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                      &lt;span style="color: #0000ff"&gt;ulong&lt;/span&gt; sinceId;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                      (&lt;span style="color: #0000ff"&gt;ulong&lt;/span&gt;.TryParse(_sinceId, &lt;span style="color: #0000ff"&gt;out&lt;/span&gt; sinceId)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                           ? Context.Status.Where(s =&amp;gt; s.Type == statusType &amp;amp;&amp;amp; s.Count == 200)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                           : Context.Status.Where(s =&amp;gt; s.Type == statusType &amp;amp;&amp;amp; s.Count == 200 &amp;amp;&amp;amp; s.SinceID == sinceId))&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                          .AsyncCallback(statuses =&amp;gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                          {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                              &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (var status &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; statuses)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                              {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                                  ob.OnNext(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Tweet(status));&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                                  _sinceId = status.StatusID;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                              }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                          })&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                          .FirstOrDefault(); &lt;span style="color: #008000"&gt;// materalize the results&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                  }))&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        .DispatcherSubscribe(SubscribeToTweet);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;That contains some custom code:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Context:&amp;nbsp; is a TwitterContext from LinqToTwitter 
&lt;li&gt;DispatcherSubscribe:&amp;nbsp; is a helper extension method which Subscribes on the ThreadPool, Observes on the Dispatcher, and then Subscribes with the specified action 
&lt;li&gt;SubscribeToTweet: a method in the base class which adds to a ObservableCollection so the UI gets updated&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;To translate the code, here is a basic flow of what’s happening:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Observable.Create wraps the subscription of another Observable.&amp;nbsp; It provides access to an IObserver &lt;em&gt;ob&lt;/em&gt; which lets you explicitly invoke OnNext(). 
&lt;li&gt;Observable.Interval will raise an observable every 60 seconds. 
&lt;li&gt;The subscription of Observable.Interval will query the TwitterContext for the next set of tweets. 
&lt;li&gt;Inside the AsyncCallback, it invokes &lt;em&gt;ob.OnNext &lt;/em&gt;as well as keeps track of the ID so the next time it queries it only gets newer tweets. 
&lt;li&gt;Finally, &lt;em&gt;DispatcherSubscribe&lt;/em&gt; will take the &lt;em&gt;Tweet&lt;/em&gt; object and add it to an &lt;em&gt;ObservableCollection&amp;lt;Tweet&amp;gt;&lt;/em&gt;, which notifies the UI.&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;As always, you should “clean up your garbage”.&amp;nbsp; In this respect I was pretty impressed with Rx as it was able to clean up the entire chain of observables with a single call to &lt;em&gt;_subscription.Dispose()&lt;/em&gt;.&amp;nbsp; Nice!&lt;/p&gt;
&lt;p&gt;In the next post I’m going to switch back to UI and completely restyle the application.&amp;nbsp; The code will hit GitHub soon as well (I promise!).&amp;nbsp; Stay tuned…&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-4334702627781245436?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/4334702627781245436/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=4334702627781245436' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/4334702627781245436'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/4334702627781245436'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2011/09/building-real-time-push-app-with.html' title='Building a Real-time Push App with Silverlight: Part 4'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/-f1uQ63FwyoI/TmU-fK3WfQI/AAAAAAAAAGc/Y26EvwnXy_4/s72-c/image_thumb%25255B15%25255D.png?imgmax=800' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-1749597089850052538</id><published>2011-08-28T15:21:00.001-07:00</published><updated>2011-08-28T19:44:44.087-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Rx'/><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><category scheme='http://www.blogger.com/atom/ns#' term='Blend'/><title type='text'>Building a Real-time Push App with Silverlight: Part 3</title><content type='html'>&lt;p&gt;In this part we’re going to fire up Expression Blend (the trial for version 5 can be found &lt;a href="http://www.microsoft.com/download/en/details.aspx?displaylang=en&amp;amp;id=9503"&gt;here&lt;/a&gt;) and do some UI work.&lt;/p&gt; &lt;p&gt;In part 2, I created a simple Twitter client which connected to the streaming API, and connected to the sampling request which brings back random tweets.&amp;nbsp; Here is the data template:&lt;/p&gt; &lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;DataTemplate&lt;/span&gt; &lt;span style="color: #ff0000"&gt;x:Key&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="TweetDataTemplate"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Grid&lt;/span&gt; &lt;span style="color: #ff0000"&gt;DataContext&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="{Binding}"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Grid.RowDefinitions&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;RowDefinition&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;RowDefinition&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Height&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Auto"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Grid.RowDefinitions&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;TextBlock&lt;/span&gt; &lt;span style="color: #ff0000"&gt;FontFamily&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="{StaticResource FontFamily}"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;FontSize&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="12"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="{Binding Text}"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;TextWrapping&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Wrap"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;TextBlock&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Grid&lt;/span&gt;.&lt;span style="color: #ff0000"&gt;Row&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="1"&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                   &lt;span style="color: #ff0000"&gt;HorizontalAlignment&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Right"&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                   &lt;span style="color: #ff0000"&gt;VerticalAlignment&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Bottom"&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                   &lt;span style="color: #ff0000"&gt;FontFamily&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="{StaticResource FontFamily}"&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                   &lt;span style="color: #ff0000"&gt;FontSize&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="13.333"&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                   &lt;span style="color: #ff0000"&gt;Foreground&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="BlueViolet"&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                   &lt;span style="color: #ff0000"&gt;Text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="{Binding ScreenName}"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;TextBlock&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Grid&lt;/span&gt;.&lt;span style="color: #ff0000"&gt;Row&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="1"&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                   &lt;span style="color: #ff0000"&gt;HorizontalAlignment&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Left"&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                   &lt;span style="color: #ff0000"&gt;VerticalAlignment&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Bottom"&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                   &lt;span style="color: #ff0000"&gt;FontFamily&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="{StaticResource FontFamily}"&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                   &lt;span style="color: #ff0000"&gt;FontSize&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="9.333"&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                   &lt;span style="color: #ff0000"&gt;Foreground&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="DarkCyan"&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                   &lt;span style="color: #ff0000"&gt;Text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="{Binding CreatedAt}"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Grid&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;DataTemplate&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This renders into something like this:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh4.ggpht.com/-ul4umD_jKFs/Tlq_U7HuoLI/AAAAAAAAAFg/pOhMiaqmxcE/s1600-h/image%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-iRU3VAO9bmM/Tlq_Ve_91LI/AAAAAAAAAFk/JCfO-MSPXhk/image_thumb%25255B2%25255D.png?imgmax=800" width="424" height="84"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The text is randomly generated from Blend’s &lt;a href="http://lmgtfy.com/?q=blend+sample+data"&gt;sample data&lt;/a&gt; capability, which is totally awesome as it allows designers to see what they’re working with, and keeps the sample data separate from the real data.&lt;/p&gt;
&lt;p&gt;While design is a matter of personal taste, and you’re bound to get disagreements between different people, if you follow some basic rules you’ll satisfy a greater audience.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Subtle gradients and small shadows 
&lt;ul&gt;
&lt;li&gt;If you take a look at all the nice interfaces, they tend to use very slight gradients and small shadows.&amp;nbsp; Most of the time you don’t even notice unless you look closely. 
&lt;li&gt;I think Microsoft’s Metro design is beautiful.&amp;nbsp; Reason?&amp;nbsp; It emphasizes text over decorations (like gradients and shadows).&amp;nbsp; This tends to lead to very clean design because there’s very little opportunity to abuse gradients and shadows.&lt;/li&gt;&lt;/ul&gt;
&lt;li&gt;Realism and light sources 
&lt;ul&gt;
&lt;li&gt;Continuing on with gradients and shadows, they should be realistic.&amp;nbsp; Look at your design from a 3D point of view.&amp;nbsp; Apply a light source from a certain angle, and then apply your shadows relative to that light source. 
&lt;li&gt;Convey distance properly&lt;/li&gt;&lt;/ul&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;Darker shadows imply being closer to the background, whereas lighter shadows imply being further away.&amp;nbsp; Use blurring to add emphasis to the distance.&lt;br&gt;&lt;a href="http://lh4.ggpht.com/-cdUtFU6yTXs/Tlr6Ob6YaBI/AAAAAAAAAFo/jaMAe5SO7mo/s1600-h/image%25255B26%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-YvKRal5ToEw/Tlr6OrRIS4I/AAAAAAAAAFs/AAg79v6y2Cc/image_thumb%25255B14%25255D.png?imgmax=800" width="240" height="37"&gt;&lt;/a&gt; 
&lt;li&gt;If you overlap planes you should apply these rules to each individual plane.&amp;nbsp; Don’t use the same border for everything.&amp;nbsp; Think about how it would look like in real life if you laid it out like that with pieces of paper.&amp;nbsp; The shadow sizes for that will be different, so you should do the same. 
&lt;li&gt;Also keep in mind that the shadows used above are &lt;em&gt;way&lt;/em&gt; too much for any application.&amp;nbsp; Be subtle!&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;
&lt;li&gt;Consistent theme 
&lt;ul&gt;
&lt;li&gt;This one seems obvious but nothing is worse than having a nice looking application bring up an unskinned dialog.&lt;/li&gt;&lt;/ul&gt;
&lt;li&gt;Usability 
&lt;ul&gt;
&lt;li&gt;If the design doesn’t serve a purpose to make it more usable, it shouldn’t be there.&amp;nbsp; Even something as simple as black on white follows this – you do that so you can read text.&amp;nbsp; However, even something as simple as that can be improved.&amp;nbsp; Take a look at why the Kindle is so successful.&amp;nbsp; The readability is better because of the lower contrast between the black and light-brown background.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;With these starting points, let’s redesign the data template.&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;DataTemplate&lt;/span&gt; &lt;span style="color: #ff0000"&gt;x:Key&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="TweetDataTemplate"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;   &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Grid&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;       &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Grid.Background&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;           &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;LinearGradientBrush&lt;/span&gt; &lt;span style="color: #ff0000"&gt;StartPoint&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="0.5,0"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;EndPoint&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="0.5,1"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;               &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;GradientStop&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Color&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="#FFDADADA"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;               &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;GradientStop&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Offset&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="1"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Color&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="#FFC8C8C8"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;           &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;LinearGradientBrush&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;       &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Grid.Background&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;       &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Grid.RowDefinitions&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;           &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;RowDefinition&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;           &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;RowDefinition&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Height&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Auto"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;       &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Grid.RowDefinitions&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;       &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;TextBlock&lt;/span&gt; &lt;span style="color: #ff0000"&gt;FontFamily&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="{StaticResource FontFamily}"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;FontSize&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="12"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="{Binding Text}"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;TextWrapping&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Wrap"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;       &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;TextBlock&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Grid&lt;/span&gt;.&lt;span style="color: #ff0000"&gt;Row&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="1"&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                  &lt;span style="color: #ff0000"&gt;HorizontalAlignment&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Right"&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                  &lt;span style="color: #ff0000"&gt;VerticalAlignment&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Bottom"&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                  &lt;span style="color: #ff0000"&gt;FontFamily&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="{StaticResource FontFamily}"&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                  &lt;span style="color: #ff0000"&gt;FontSize&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="13.333"&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                  &lt;span style="color: #ff0000"&gt;Foreground&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="BlueViolet"&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                  &lt;span style="color: #ff0000"&gt;Text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="{Binding ScreenName}"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;       &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;TextBlock&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Grid&lt;/span&gt;.&lt;span style="color: #ff0000"&gt;Row&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="1"&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                  &lt;span style="color: #ff0000"&gt;HorizontalAlignment&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Left"&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                  &lt;span style="color: #ff0000"&gt;VerticalAlignment&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Bottom"&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                  &lt;span style="color: #ff0000"&gt;FontFamily&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="{StaticResource FontFamily}"&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                  &lt;span style="color: #ff0000"&gt;FontSize&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="9.333"&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                  &lt;span style="color: #ff0000"&gt;Foreground&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="#FF003D8F"&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                  &lt;span style="color: #ff0000"&gt;Text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="{Binding CreatedAt}"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;       &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Border&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Grid&lt;/span&gt;.&lt;span style="color: #ff0000"&gt;RowSpan&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="2"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;BorderBrush&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="#FF999999"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;BorderThickness&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="0,0,0,1"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;       &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Border&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Grid&lt;/span&gt;.&lt;span style="color: #ff0000"&gt;RowSpan&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="2"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;BorderBrush&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="White"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;BorderThickness&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="0,1,0,0"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;   &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Grid&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;DataTemplate&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;After these changes, it looks like this:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh3.ggpht.com/-TgxXvJqHk-c/Tlr6O9P56uI/AAAAAAAAAFw/Nc5v5nLapLc/s1600-h/image%25255B31%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px 5px 0px 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="left" src="http://lh5.ggpht.com/-fTL8wgr5ebs/Tlr6PGkqyeI/AAAAAAAAAF0/O98iakwvqGc/image_thumb%25255B17%25255D.png?imgmax=800" width="304" height="99"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Did you notice the gradient?&amp;nbsp; You might think after seeing it here to adjust the gradients more so you can see it.&amp;nbsp; That would be a mistake.&amp;nbsp; See below.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh5.ggpht.com/-jLd2xQIBIW8/Tlr6PfKpCBI/AAAAAAAAAF4/x3qjb1XqB0o/s1600-h/image%25255B69%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px 5px 0px 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://lh6.ggpht.com/--uPF_IEo6LM/Tlr6PpL9YDI/AAAAAAAAAF8/UxqCqYW3Wl4/image_thumb%25255B47%25255D.png?imgmax=800" width="336" height="198"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To the right is the exact same thing, but stacked vertically three times.&amp;nbsp; When this happens the subtle difference between the top and bottom of the control is more pronounced, so it looks like multiple panels are aligned together.&lt;a href="http://lh3.ggpht.com/-QRud-f9oNl0/Tlr6PwZxYEI/AAAAAAAAAGA/n4ZgvQHGU2g/s1600-h/image%25255B64%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px 5px 0px 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="left" src="http://lh3.ggpht.com/-QHLW-sKfPfI/Tlr6P_c9qLI/AAAAAAAAAGE/kJ0Z8VgS3xg/image_thumb%25255B44%25255D.png?imgmax=800" width="336" height="198"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;However, there’s still a little touch you can add.&amp;nbsp; The white and gray borders are only 1 pixel high, but that’s the little touch needed to make it look crisp.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Finally, let’s see the before and after (or eh…rather after and before, because I took the screenshot backwards :P):&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh6.ggpht.com/-xEyFAxujR8o/Tlr6QbtqRTI/AAAAAAAAAGI/KKzuwUmnh6o/s1600-h/image%25255B74%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-tzZ8AVtNv0M/Tlr6QmHJHnI/AAAAAAAAAGM/H1SYEqT6cis/image_thumb%25255B50%25255D.png?imgmax=800" width="617" height="342"&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-1749597089850052538?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/1749597089850052538/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=1749597089850052538' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/1749597089850052538'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/1749597089850052538'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2011/08/building-real-time-push-app-with_28.html' title='Building a Real-time Push App with Silverlight: Part 3'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/-iRU3VAO9bmM/Tlq_Ve_91LI/AAAAAAAAAFk/JCfO-MSPXhk/s72-c/image_thumb%25255B2%25255D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-8210359914208317045</id><published>2011-08-27T14:16:00.001-07:00</published><updated>2011-08-28T11:16:47.002-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Rx'/><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><title type='text'>Building a Real-time Push App with Silverlight: Part 2</title><content type='html'>&lt;p&gt;Let’s review the main Rx code from last time:&lt;/p&gt; &lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; IObservable&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt; GetJsonStreams()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;  var request = GetRequest();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;  &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; Observable.FromAsyncPattern&amp;lt;WebResponse&amp;gt;(request.BeginGetResponse, request.EndGetResponse)()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    .Select(wr =&amp;gt; wr.GetResponseStream())&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    .Select(str =&amp;gt; Observable.FromAsyncPattern&amp;lt;&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;[], &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt;(str.BeginRead, str.EndRead))&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    .SelectMany(ParseJson);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;One thing I didn’t like about this was that the web request object was created regardless of whether the Observable gets a subscription or not.&amp;nbsp; This is potentially wasted resources, and I wanted to refactor this to be completely lazy.&lt;/p&gt;
&lt;p&gt;And with this I started to run into my first “huh?” moments with Rx: I blocked the UI thread.&amp;nbsp; How did I do that?&amp;nbsp; I started down the path of exploring some more of the Rx methods, which lead me to &lt;em&gt;Create&lt;/em&gt;, which lets you manually call &lt;em&gt;OnNext.&amp;nbsp; &lt;/em&gt;With this train of thought, I came up with something like this:&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;return&lt;/span&gt; Observable.Create&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt;(obs =&amp;gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;  var request = GetRequest();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;  var response = Observable.FromAsyncPattern&amp;lt;WebResponse&amp;gt;(request.BeginGetResponse, request.EndGetResponse)().First();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;  var str = response.GetResponseStream();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;  var reader = Observable.FromAsyncPattern&amp;lt;&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;[], &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt;(str.BeginRead, str.EndRead);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;  &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (var json &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; ParseJson(reader))&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;      obs.OnNext(json);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;  obs.OnCompleted();&lt;br&gt;&amp;nbsp; &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; str;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;});&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Great!&amp;nbsp; The initialization of the web request only occurs when subscribed!&amp;nbsp; And it will even dispose the stream (by returning &lt;em&gt;str&lt;/em&gt;) upon unsubscription.&amp;nbsp; I ran the app and the UI thread immediately blocked.&amp;nbsp; What happened?&lt;/p&gt;
&lt;p&gt;Rx has the concept of subscription and observation, and provides a way to subscribe and observe on different threads.&amp;nbsp; Here is the original code that subscribed:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;s.GetJsonStreams()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;   .ObserveOnDispatcher()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;   .Subscribe(x =&amp;gt; Text = x);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Can you spot the error?&amp;nbsp; I explicitly told Rx to observe on the dispatcher thread, because I want the action inside &lt;em&gt;Subscribe&lt;/em&gt; to be invoked on the UI thread, but I didn’t specify where I want to set up the subscription.&amp;nbsp; Since I left it out, it uses the current thread, which happens to be the UI thread.&amp;nbsp; To solve this, it’s as simple as doing this:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;s.GetJsonStreams()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;  .SubscribeOn(Scheduler.ThreadPool)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;  .ObserveOnDispatcher()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;  .Subscribe(x =&amp;gt; Text = x);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;That’s it!&amp;nbsp; Easy!&amp;nbsp; This also follows one of the most important guidelines when using Rx: &lt;strong&gt;Subscription and Observation should be done as late as possible&lt;/strong&gt;, typically just before the &lt;em&gt;Subscribe&lt;/em&gt;.&amp;nbsp; Anything more and you’ll likely make Rx spawn more threads than are necessary or some other nasty bugs.&amp;nbsp; &lt;a href="http://en.wikipedia.org/wiki/KISS_principle"&gt;KISS&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;Now with that out of the way, let’s replace the boring TextBlock with something more usable.&amp;nbsp; First, I need to parse all the JSON streams I’m getting into bindable models.&amp;nbsp; To do that, I upgraded my StreamReader component and threw in System.Json for some basic parsing:&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; TweetParser&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; _stack;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; StringBuilder _sb = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; StringBuilder();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; IEnumerable&amp;lt;Tweet&amp;gt; Parse(&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;[] buffer, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; count)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; count; i++)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            var current = (&lt;span style="color: #0000ff"&gt;char&lt;/span&gt;)buffer[i];&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            _sb.Append(current);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (current == &lt;span style="color: #006080"&gt;'{'&lt;/span&gt;) _stack++;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (current == &lt;span style="color: #006080"&gt;'}'&lt;/span&gt;) _stack--;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (_stack == 0 &amp;amp;&amp;amp; _sb.Length &amp;gt; 0)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                Tweet tweet;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                var &lt;span style="color: #0000ff"&gt;value&lt;/span&gt; = JsonValue.Parse(_sb.ToString());&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;value&lt;/span&gt; &lt;span style="color: #0000ff"&gt;is&lt;/span&gt; JsonObject &amp;amp;&amp;amp; Tweet.TryParse((JsonObject)&lt;span style="color: #0000ff"&gt;value&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;out&lt;/span&gt; tweet))&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                    &lt;span style="color: #0000ff"&gt;yield&lt;/span&gt; &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; tweet;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                _sb.Clear();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Nothing overly complicated.&amp;nbsp; Next, the Tweet object:&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Tweet&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; JsonObject _json;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; TryParse(JsonObject &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;out&lt;/span&gt; Tweet tweet)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;value&lt;/span&gt;.ContainsKey(&lt;span style="color: #006080"&gt;"text"&lt;/span&gt;) &amp;amp;&amp;amp; &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;.ContainsKey(&lt;span style="color: #006080"&gt;"user"&lt;/span&gt;))&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            tweet = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Tweet(&lt;span style="color: #0000ff"&gt;value&lt;/span&gt;);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        tweet = &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; Tweet(JsonObject json)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        _json = json;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Text&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        get { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; _json[&lt;span style="color: #006080"&gt;"text"&lt;/span&gt;].ToValueString(); }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; ScreenName&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        get { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; _json[&lt;span style="color: #006080"&gt;"user"&lt;/span&gt;][&lt;span style="color: #006080"&gt;"screen_name"&lt;/span&gt;].ToValueString(); }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; TweetEx&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; ToValueString(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt; JsonValue s)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; s.ToString().Trim(&lt;span style="color: #006080"&gt;'"'&lt;/span&gt;);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;To keep things simple I’m only extracting the screen name and text.&amp;nbsp; I won’t bore you setting up the views since it’s just simple ListBox bound to an ObservableCollection&amp;lt;Tweet&amp;gt;, and a DataTemplate for Tweet.&amp;nbsp; When it’s all said and done, we see something like this:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh4.ggpht.com/-WFTaVk0Cjls/TlqFsoenmOI/AAAAAAAAAFY/MEt0MHis3dY/s1600-h/image5.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-sVzoQRx_V2s/TlqFswXVhUI/AAAAAAAAAFc/d9nLfBSrARA/image_thumb3.png?imgmax=800" width="644" height="431"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Performance is still good at 2-5% CPU, even though we’re scrolling through 1000 items in near real-time.&lt;/p&gt;
&lt;p&gt;Stay tuned for part 3, when we introduce Expression Blend and go into basics of UI design.&amp;nbsp; Also, most of this will hit GitHub very soon.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-8210359914208317045?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/8210359914208317045/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=8210359914208317045' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/8210359914208317045'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/8210359914208317045'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2011/08/building-real-time-push-app-with_27.html' title='Building a Real-time Push App with Silverlight: Part 2'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/-sVzoQRx_V2s/TlqFswXVhUI/AAAAAAAAAFc/d9nLfBSrARA/s72-c/image_thumb3.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-620858252525935120</id><published>2011-08-26T19:54:00.001-07:00</published><updated>2011-08-28T15:22:35.763-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Rx'/><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><title type='text'>Building a Real-time Push App with Silverlight: Part 1</title><content type='html'>&lt;p&gt;This is the beginning of a multi-part series where I’ll be building an interactive application with Silverlight 5 (still beta as of this post).&amp;nbsp; It will be built from the ground up and designed predominantly from a “push data” point of view, where the application is reacting to events in real-time, rather than a more traditional “pulling” point of view.&amp;nbsp; This type of application has exploded with the popularity of social networking and has made a lot of the traditional methods of building applications obsolete.&lt;/p&gt; &lt;p&gt;The best example of this shift is from Twitter.&amp;nbsp; When it first came out, it was (and still is predominantly) a “pull” model.&amp;nbsp; You have 200 API requests an hour, and you pull Twitter whenever you want to check if there are tweets of people you follow.&amp;nbsp; That is changing with the &lt;a href="https://dev.twitter.com/docs/streaming-api"&gt;Streaming API&lt;/a&gt; where data is “pushed” to you as it comes.&amp;nbsp; This changes the way you write your code and requires a mind shift much like from for loops to LINQ.&lt;/p&gt; &lt;p&gt;The primary purpose of this series is build a real-time push application from beginning to end, and to show any problems I run along the way, and how I managed to solve them.&amp;nbsp; This will be my first attempt at building a Silverlight application as well as learning &lt;a href="http://msdn.microsoft.com/en-us/data/gg577609"&gt;Reactive Extensions&lt;/a&gt; (Rx), so I’m bound to run into newbie mistakes.&amp;nbsp; If you have any tips or pointers please let me know!&lt;/p&gt; &lt;p&gt;Also, rather than doing this from a purely technical point of view, I’m also going to put on my designer hat and talk about UI design, and make it look good with Expression Blend when I get to designing the UI in later parts of this series.&amp;nbsp; I feel that this is often overlooked and can result in a lot of wasted work and lead to frustration.&lt;/p&gt; &lt;p&gt;This first post will be to get up and running and connected to Twitter with the Streaming API. This was chosen primarily because it is so much data can be pushed through and it can be used to demonstrate how to write a high performance Silverlight application.&amp;nbsp; It’s one thing to write something maintainable, and another altogether to make it run fast as well.&amp;nbsp; I’ve worked on too many WPF projects where performance took a back seat, and in WPF particularly this tends to create some massive technical debt.&amp;nbsp; The Silverlight/WPF technology stack is an exception to the rule and you should definitely think about performance from the start.&lt;/p&gt; &lt;p&gt;Well let’s get started!&amp;nbsp; We will connect to Twitter, convert it to an Observable, and then display tweets on the UI.&lt;/p&gt; &lt;p&gt;First, let’s create our TwitterStream class:&lt;/p&gt; &lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; TwitterStream&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt;     {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; TwitterStream()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;         {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;             &lt;span style="color: #008000"&gt;// this allows http authentication to work&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;             WebRequest.RegisterPrefix(&lt;span style="color: #006080"&gt;"http://"&lt;/span&gt;, System.Net.Browser.WebRequestCreator.ClientHttp);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;         }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; StreamParser parser = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; StreamParser();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Username { get; set; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Password { get; set; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; HttpWebRequest GetRequest()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;         {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;             var request = WebRequest.CreateHttp(&lt;span style="color: #006080"&gt;"http://stream.twitter.com/1/statuses/sample.json?delimited=length"&lt;/span&gt;);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;             request.UseDefaultCredentials = &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;             request.Credentials = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; NetworkCredential(Username, Password);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; request;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;         }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; IObservable&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt; GetJsonStreams()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt;         {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum24"&gt;  24:&lt;/span&gt;             var request = GetRequest();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum25"&gt;  25:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; Observable.FromAsyncPattern&amp;lt;WebResponse&amp;gt;(request.BeginGetResponse, request.EndGetResponse)()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum26"&gt;  26:&lt;/span&gt;                 .Select(wr =&amp;gt; wr.GetResponseStream())&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum27"&gt;  27:&lt;/span&gt;                 .Select(str =&amp;gt; Observable.FromAsyncPattern&amp;lt;&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;[], &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt;(str.BeginRead, str.EndRead))&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum28"&gt;  28:&lt;/span&gt;                 .SelectMany(ParseJson);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum29"&gt;  29:&lt;/span&gt;         }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum30"&gt;  30:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum31"&gt;  31:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; IEnumerable&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt; ParseJson(Func&amp;lt;&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;[], &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;, IObservable&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt;&amp;gt; reader)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum32"&gt;  32:&lt;/span&gt;         {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum33"&gt;  33:&lt;/span&gt;             var buffer = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;[256];&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum34"&gt;  34:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; bytesRead;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum35"&gt;  35:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum36"&gt;  36:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;while&lt;/span&gt; ((bytesRead = reader(buffer, 0, buffer.Length).Single()) &amp;gt; 0)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum37"&gt;  37:&lt;/span&gt;             {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum38"&gt;  38:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (var json &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; parser.Parse(buffer, bytesRead))&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum39"&gt;  39:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;yield&lt;/span&gt; &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; json;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum40"&gt;  40:&lt;/span&gt;             }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum41"&gt;  41:&lt;/span&gt;         }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum42"&gt;  42:&lt;/span&gt;     }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And that’s all there is to it!&amp;nbsp; The most complicated part is probably parsing of the JSON documents themselves, which I refactored into its own class.&amp;nbsp; The algorithm in the parser is pretty primitive, as it just looks for opening { and closing } and calls that a document – nothing more, nothing less.&amp;nbsp; Note that this uses the deprecated basic HTTP authentication.&amp;nbsp; Sooner or later it will be shut down and OAuth will be required, so I will upgrade when that happens as I want to keep the amount of written code to a minimum.&lt;/p&gt;
&lt;p&gt;Perhaps the more interesting bit is this part with Rx:&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;Observable.FromAsyncPattern&amp;lt;WebResponse&amp;gt;(request.BeginGetResponse, request.EndGetResponse)()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;  .Select(wr =&amp;gt; wr.GetResponseStream())&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;  .Select(str =&amp;gt; Observable.FromAsyncPattern&amp;lt;&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;[], &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt;(str.BeginRead, str.EndRead))&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;  .SelectMany(ParseJson);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The API takes some getting used to, but once you “tune in” things start to make sense.&amp;nbsp; The &lt;em&gt;FromAsyncPattern &lt;/em&gt;essentially wraps the &lt;a href="http://msdn.microsoft.com/en-us/library/ms228969.aspx"&gt;APM pattern&lt;/a&gt;’s Begin/End calls into a single Func&amp;lt;&amp;gt;, which when invoked gets you the result as if you called End(), however without all the tedious AsyncCallback implementation.&lt;/p&gt;
&lt;p&gt;The nice thing about this wrapper Func is that the code starts to look synchronous, even though it is using the ThreadPool behind the scenes.&amp;nbsp; Next, the response is projected into its response stream, which again is converted to another Observable for reading bytes from the stream until finally it goes into the &lt;em&gt;ParseJson&lt;/em&gt; method which projects string results.&amp;nbsp; This is both good and bad.&amp;nbsp; Good in that it can make asynchronous code look short and succinct (in this example I’ve wrapped 2 APM pattern calls in 2 lines of code), bad in that anyone inexperienced with Rx will get lost pretty fast.&lt;/p&gt;
&lt;p&gt;Rx thus far has been a fairly high learning curve.&amp;nbsp; Maybe it’s just me.&amp;nbsp; When I read about it from others, or from seminars, it all makes sense and I generally don’t have any questions.&amp;nbsp; Trying to use it directly is another story, as there are so many overloads it’s easy to get overwhelmed.&amp;nbsp; I feel like Intellisense is making things worse!&lt;/p&gt;
&lt;p&gt;Carrying on, the code above actually doesn’t do anything yet.&amp;nbsp; First, you must &lt;em&gt;Subscribe&lt;/em&gt; to an observable before it does something, similar to you must foreach on a IEnumerable before it starts pulling data.&lt;/p&gt;
&lt;p&gt;To finish off, let’s create a simple Window with a TextBlock bound to a Text property.&amp;nbsp; This is the constructor:&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; MainPage()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;   InitializeComponent();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;   DataContext = &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;   var s = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; TwitterStream();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;   s.Username = &lt;span style="color: #006080"&gt;"blingcoder"&lt;/span&gt;;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;   s.Password = &lt;span style="color: #006080"&gt;"1234567"&lt;/span&gt;;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;   s.GetJsonStreams()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;       .ObserveOnDispatcher()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;       .Subscribe(x =&amp;gt; Text = x);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Perhaps one of the nicest features of Rx is automatic thread switching between background threads and UI threads.&amp;nbsp; Above, there is a call to &lt;em&gt;ObserveOnDispatcher&lt;/em&gt;, which as the name implies it observes to events on the Dispatcher thread :-).&amp;nbsp; Rx automatically handles switching to the UI thread so when &lt;em&gt;Subscribe&lt;/em&gt; occurs we’re on the UI thread.&lt;/p&gt;
&lt;p&gt;Performance is also very good so far, only maxing out at 5% CPU for what appears to be a continuous flood of tweets from random people.&lt;/p&gt;
&lt;p&gt;And there you have it!&amp;nbsp; A completely asynchronous streaming Twitter client in roughly 20 lines of code (minus the parsing).&amp;nbsp; Stay tuned for part 2….&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-620858252525935120?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/620858252525935120/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=620858252525935120' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/620858252525935120'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/620858252525935120'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2011/08/building-real-time-push-app-with.html' title='Building a Real-time Push App with Silverlight: Part 1'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-5834173931368468117</id><published>2011-08-19T10:22:00.000-07:00</published><updated>2011-08-21T19:40:22.761-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Logging'/><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><title type='text'>Injecting Logger Instances Via Convention With Unity</title><content type='html'>&lt;p&gt;Let's say you have something like this:&lt;/p&gt; &lt;pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; MyClass {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ILog Logger { &lt;span style="color: #0000ff"&gt;get&lt;/span&gt;; &lt;span style="color: #0000ff"&gt;set&lt;/span&gt;; }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;}&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;And you simply want Unity to inject an instance of ILog such that its name is requestingDependency.GetType().FullName, which in this case would be Full.Namespace.MyClass.&lt;br&gt;&lt;br&gt;I'll leave it up to the exercise of the reader, but if you search for 'log4net and Unity' you will find some working solutions which IMO are way too long to solve this.&amp;nbsp; I have obviously taken for granted the features of Windsor and Autofac too much because I expected something like this to be easily done in 2-3 lines of code.&lt;br&gt;&lt;br&gt;After a lot of cursing I've come up with something that's almost as short and gets the job done:&lt;/p&gt;&lt;pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; LoggingExtension : UnityContainerExtension
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Initialize()
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;        {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Context.Strategies.AddNew(UnityBuildStage.PreCreation);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; LogBuilderStrategy : BuilderStrategy
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;        {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; Stack buildKeys = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Stack();
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; PreBuildUp(IBuilderContext context)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;            {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;                var type = ((NamedTypeBuildKey)context.BuildKey).Type;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (type == &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(ILog))
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;                {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;                    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.buildKeys.Count &amp;lt; 1)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;                        &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; InvalidOperationException("&lt;span style="color: #8b0000"&gt;Log instances cannot be resolved directly.&lt;/span&gt;");
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;                    context.Existing = LogManager.GetLog(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.buildKeys.Peek());
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;                }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;                &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.buildKeys.Push(type);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;            }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; PostBuildUp(IBuilderContext context)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;            {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;                &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.buildKeys.Pop();
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;            }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;/pre&gt;
&lt;p&gt;If you noticed, I had to cast to NamedTypeBuildKey, which unfortunately means I'm still stuck with Unity 1.2...&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-5834173931368468117?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/5834173931368468117/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=5834173931368468117' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/5834173931368468117'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/5834173931368468117'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2011/08/injecting-logger-instances-via.html' title='Injecting Logger Instances Via Convention With Unity'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-4645396798077659122</id><published>2011-08-16T07:51:00.000-07:00</published><updated>2011-08-16T07:51:39.844-07:00</updated><title type='text'>Adding Scripting to your Tool Belt</title><content type='html'>One of the most important things for any developer is to be well rounded. &amp;nbsp;They should know about functional, imperative, object-oriented, aspect-oriented programming, among others. &amp;nbsp;They should know the difference between dynamic and static languages. &amp;nbsp;They should know the difference between scripting, interpreted, compiled languages.&lt;br /&gt;
&lt;br /&gt;
Why? &amp;nbsp;It opens your mindset. &amp;nbsp;It lets you see things in a different light, which ultimately changes the way you will write your code, and for the better.&lt;br /&gt;
&lt;br /&gt;
The best example is when C# introduced lambdas and LINQ. &amp;nbsp;All of a sudden, the masses saw the benefits of functional programming style and how it &lt;b&gt;greatly&lt;/b&gt;&amp;nbsp;makes code succinct.&lt;br /&gt;
&lt;br /&gt;
Here, I give an example of what knowing a little about Powershell did to save me a lot of time.&lt;br /&gt;
&lt;br /&gt;
I use git-tfs to make my day job a little less painful every day, because I cannot stand TFS, at all. &amp;nbsp;In their latest release, they decided not to tag every changeset. &amp;nbsp;I like my things consistent, so I decided to go back in history to untag all the changesets.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, git doesn't have a mass untag, and you must untag each branch individually with "git tag -d name_of_tag".&lt;br /&gt;
&lt;br /&gt;
This is how you do it with Powershell:&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;50000..40000 | % { git tag -d "tfs/default/C$_" }&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
50000..40000 creates an list of numbers from 50,000 to 40,000, then it gets piped (|) into a foreach loop (%) to run the git tag command by generating the tag name with the current loop item ($_).&lt;br /&gt;
&lt;br /&gt;
Why was this awesome? &amp;nbsp;I didn't have to open up Visual Studio, or a text editor, or anything. &amp;nbsp;I just typed it into the shell.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-4645396798077659122?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/4645396798077659122/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=4645396798077659122' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/4645396798077659122'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/4645396798077659122'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2011/08/adding-scripting-to-your-tool-belt.html' title='Adding Scripting to your Tool Belt'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-4897028493740795309</id><published>2011-06-23T17:55:00.001-07:00</published><updated>2011-06-24T08:16:56.431-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Tools'/><title type='text'>Tools I Use To Do What I Do</title><content type='html'>&lt;p&gt;It’s been a while since I last blogged, but I want to get back into it….I just haven’t thought about what I wanna blog about yet.&amp;nbsp; I’m thinking of doing some sort of multi-part series on a topic but haven’t decided on what yet.&amp;nbsp; Nonetheless, just to get the ball rolling again here’s a quick blog post on some of the tools I use to do my every day job that’s in addition to your typical .NET developer tool chain.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;General&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.tcbmi.com/strokeit/"&gt;StrokeIt&lt;/a&gt;:&amp;nbsp; Funny name aside, on any clean install of Windows this is the &lt;strong&gt;first&lt;/strong&gt; thing I install.&amp;nbsp; I load up IE and I download this, followed by Chrome/Firefox.&amp;nbsp; It is a mouse gesture program that affects all of Windows.&amp;nbsp; By holding down the right mouse button, and making gestures you can do common tasks like minimize (drag SW), maximize (drag NE), close (draw a C), and others.&amp;nbsp; It’s much faster than clicking the minimize/maximize buttons.&amp;nbsp; For web browsing, creating and close tabs are drag SE and drag NW respectively.&amp;nbsp; Back is W.&amp;nbsp; Forward is E.&amp;nbsp; Working this way is faster than any keyboard shortcut.&lt;/p&gt; &lt;p&gt;&lt;a href="http://sourceforge.net/projects/console/"&gt;Console2&lt;/a&gt;:&amp;nbsp; It’s not a necessity, but it’s nice to be able to use a console with a better looking font.&amp;nbsp; You can easily customize to run another shell, and in my case I have Powershell as the shell.&lt;/p&gt; &lt;p&gt;&lt;a href="http://virtuawin.sourceforge.net/"&gt;VirtuaWin&lt;/a&gt;:&amp;nbsp; Ironically I don’t use any virtual desktops, but this app creates a nice middle click on any window that lets you mark it as ‘always on top’.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.vim.org/"&gt;Vim&lt;/a&gt;:&amp;nbsp; It was an awful, painful 2 weeks to learn this thing but I’m sure glad I did.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Development/Visual Studio&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.jetbrains.com/resharper/"&gt;Resharper&lt;/a&gt;:&amp;nbsp; This one doesn’t need much mentioning as anyone serious about programming in .NET has either heard of it, use it, or use one of its competitors like &lt;a href="http://www.devexpress.com/Products/Visual_Studio_Add-in/Coding_Assistance/"&gt;CodeRush&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;&lt;a href="http://visualstudiogallery.msdn.microsoft.com/465a0d53-5133-4edd-a0cd-94484fe3d853"&gt;AllMargins&lt;/a&gt;:&amp;nbsp; This hidden gem is an awesome extension has brings a bunch of very useful features to the editor.&amp;nbsp; It brings structural highlighting, highlighting matching words under caret, and RockScroll inspired scroll bar, and it does it all with little to no cost in performance.&lt;/p&gt; &lt;p&gt;&lt;a href="http://visualstudiogallery.msdn.microsoft.com/d0d33361-18e2-46c0-8ff2-4adea1e34fef/"&gt;Productivity Power Tools&lt;/a&gt;:&amp;nbsp; There’s only 2 that I use here: document tabs, and moving lines.&amp;nbsp; All the rest are either eye candy, negligible enhancements, or just plain too slow to be any use in large solutions (solution navigator I’m looking at you!!).&lt;/p&gt; &lt;p&gt;&lt;a href="http://visualstudiogallery.msdn.microsoft.com/1a67eee3-fdd1-4745-b290-09d649d07ee0"&gt;XAML Intellisense Presenter&lt;/a&gt;:&amp;nbsp; This is a must-have for anyone who works with XAML in VS regularly.&amp;nbsp; Resharper 6 may soon make this obsolete, however…&lt;/p&gt; &lt;p&gt;&lt;a href="http://wiki.sharpdevelop.net/ILSpy.ashx"&gt;ILSpy&lt;/a&gt;/&lt;a href="http://www.jetbrains.com/decompiler/"&gt;dotPeek&lt;/a&gt;:&amp;nbsp; Decompilers.&amp;nbsp; ‘nuff said.&lt;/p&gt; &lt;p&gt;&lt;a href="http://snoopwpf.codeplex.com/"&gt;Snoop&lt;/a&gt;:&amp;nbsp; Staple tool for WPF developers to inspect the visual/logical tree.&amp;nbsp; There’s also &lt;a href="http://wpfinspector.codeplex.com/"&gt;WPF Inspector&lt;/a&gt; which has a much nicer UI, but unfortunately doesn’t perform as fast.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Profiling&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.red-gate.com/products/dotnet-development/dotnet-developer-bundle/"&gt;ANTS&lt;/a&gt;/&lt;a href="http://www.jetbrains.com/profiler/"&gt;dotTrace&lt;/a&gt;/&lt;a href="http://www.yourkit.com/dotnet/download/"&gt;YourKit&lt;/a&gt;/etc:&amp;nbsp; I’ve used many performance/memory profilers, and those 3 are the ones I like the most.&amp;nbsp; Unfortunately, they all do things the others don’t, and all these things are very useful, so you still end up needing to use all of them to fix the particular problem you’re working on.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/windows/hardware/gg463009"&gt;WinDbg&lt;/a&gt;: It isn’t every day I use this, but I’m sure glad to know that such a thing exists and the amount of power it gives me.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Scripting&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://powergui.org/index.jspa"&gt;PowerGUI&lt;/a&gt;:&amp;nbsp; Best tool I found for editing PowerShell.&amp;nbsp; The intellisense is great and has all the things you were expect when debugging through scripts.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Miscellaneous&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.baremetalsoft.com/baretail/"&gt;BareTail&lt;/a&gt;:&amp;nbsp; Amazing program which watches log files in real time and can highlight rows based on a search pattern.&lt;/p&gt; &lt;p&gt;&lt;a href="http://technet.microsoft.com/en-us/scriptcenter/dd742419"&gt;PowerShell&lt;/a&gt;/&lt;a href="http://cygwin.org/"&gt;Cygwin&lt;/a&gt;/&lt;a href="http://www.mingw.org/wiki/MSYS"&gt;MSYS&lt;/a&gt;:&amp;nbsp; I used to be a Cygwin/MSYS user because back in the day I liked to install a different Linux distribution every week so I learned some basic Bash commands and that carried over to Windows.&amp;nbsp; Since PowerShell now exists, we have a real shell in Windows, so I’ve switched over to learn it, since as a Windows developer it’s more applicable to the kind of work I do.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;And there’s more but that’s enough for now!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-4897028493740795309?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/4897028493740795309/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=4897028493740795309' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/4897028493740795309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/4897028493740795309'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2011/06/tools-i-use-to-do-what-i-do.html' title='Tools I Use To Do What I Do'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-2091452392570721154</id><published>2011-05-20T19:57:00.001-07:00</published><updated>2011-05-20T20:25:09.779-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Tools'/><title type='text'>Taking a Quick Look at .NET Decompilers</title><content type='html'>&lt;p&gt;Decompilers in the .NET space has changed a lot since the announcement from Red Gate that they were going to start charging for Reflector, which was the defacto most important/useful tool in any developer’s tool belt.&lt;/p&gt; &lt;p&gt;This blog post will be a quick overview to take a look at all the new contenders that have cropped up in the .NET space to see if any of them can dethrone Reflector as the decompiler of choice.&amp;nbsp; This is only taking a look at the tools as a stand alone product and excludes any IDE integration.&lt;/p&gt; &lt;p&gt;To start, let’s take a look at Reflector.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;a href="http://www.reflector.net/"&gt;Red Gate Reflector&lt;/a&gt; (7.1.0.143)&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Having been around for years, Reflector is a rock solid product that sets the standard for everything else.&amp;nbsp; It has a simple straight forward interface and has a large following with many 3rd party addins.&amp;nbsp; It has a search which lets you find types, and an analyzer which shows you incoming and outgoing calls for any method.&amp;nbsp; It also has the most options for decompiling, giving choices from C# to VB and even Delphi.&lt;/p&gt; &lt;p&gt;Another useful feature is being able change the framework from .NET to WPF to Silverlight.&lt;/p&gt; &lt;p&gt;As of this version it looks like they added tabs, but it for me it only used one at a time…perhaps a limitation of the trial version.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;a href="http://wiki.sharpdevelop.net/ilspy.ashx"&gt;ILSpy&lt;/a&gt; (1.0.0.822)&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;This open source offering at this point looks the same as Reflector did just before Red Gate took over.&amp;nbsp; It has all the necessities, including search and analyze.&amp;nbsp; It can only view one thing at a time, and doesn’t have support for addins yet.&amp;nbsp; However, progress on this project is blazing fast and it’s only a matter of time before it reaches feature parity with the rest.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;a href="http://www.telerik.com/products/decompiling.aspx"&gt;JustDecompile Beta&lt;/a&gt; (2011.1.516.2)&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;First impression was, damn, this is a nice pretty WPF app.&amp;nbsp; Onwards, it has a predefined assembly list of .NET2, 4, and Silverlight, which is nice.&amp;nbsp; What’s nicer is that you can save a predefined list for use later, a feature that’s absent from the others.&amp;nbsp; It has search by type, and search by symbol, however, the search is noticeably slower than everything else I tried.&amp;nbsp; Also, the actual decompiling is much slower than the rest as well.&amp;nbsp; Like ILSpy, it can only view one thing at a time.&lt;/p&gt; &lt;p&gt;Decompiling to C# and VB are supported, but no IL yet.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;a href="http://www.jetbrains.com/decompiler/"&gt;dotPeek EAP&lt;/a&gt; (1.0.0.1219)&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;I tried an EAP build and I was blown away.&amp;nbsp; I may be biased because I’m a Resharper user, but having almost all of the keyboard shortcuts I have in my muscle memory work in dotPeek was a welcome surprise.&amp;nbsp; The keyboard navigation makes dotPeek &lt;strong&gt;by far&lt;/strong&gt; the best tool for navigating.&amp;nbsp; While the others have searches, they only do so at the type level.&amp;nbsp; With dotPeek (just like Resharper), you can search by type, current type, and even private members.&amp;nbsp; Inheritance searching like finding implementations, etc., all of that works.&amp;nbsp; Simply amazing.&amp;nbsp; Oh, and it also has full tab support.&lt;/p&gt; &lt;p&gt;It was also fast as well, which was a surprise considering it’s searching through the entire framework.&amp;nbsp; Searching all symbols for “m_” brought a list up in 2 seconds, and subsequent keystrokes narrowing it down occurred within half a second.&lt;/p&gt; &lt;p&gt;The downside?&amp;nbsp; No support for decompiling to IL, and lambdas aren’t fully supported yet.&amp;nbsp; I’m sure these will be done by the time it’s released.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;I guess the most important thing I should be looking at is the actual decompiler, rather than the bells and whistles. If that’s what I looked at, this would be a pretty boring post because only Reflector is able to decompile everything out there.&lt;/p&gt; &lt;p&gt;JustDecompile failed to decompile some of the assemblies I threw it at it.&amp;nbsp; dotPeek at this stage doesn’t have good lambda support (if at all).&amp;nbsp; ILSpy decompiles very well at this point and I’d have to go out of my way to find an example where Reflector does it better than ILSpy.&lt;/p&gt; &lt;p&gt;In conclusion, I love dotPeek just because of the awesomeness that is Resharper keyboard shortcuts.&amp;nbsp; For everything else, ILSpy does the job.&lt;/p&gt; &lt;p&gt;I’m actually pretty thankful that Red Gate decided to charge money for Reflector, because that inspired so much competition and we already have 3 viable replacements, all of which are free -- something that wouldn’t have happened if Reflector remained free.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-2091452392570721154?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/2091452392570721154/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=2091452392570721154' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/2091452392570721154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/2091452392570721154'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2011/05/taking-quick-look-at-net-decompilers.html' title='Taking a Quick Look at .NET Decompilers'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-3566176541537863901</id><published>2011-05-08T08:51:00.001-07:00</published><updated>2011-05-08T09:00:40.724-07:00</updated><title type='text'>Simple App to Preview Fonts</title><content type='html'>&lt;p&gt;I spent a good few hours yesterday trying out a new programming font.&amp;nbsp; It’s a personal thing.&amp;nbsp; I like switch fonts every couple weeks, and while Consolas is an excellent font and I have nothing against it, to me, it’s….too simple.&amp;nbsp; For most people, the defaults are just fine, and they can’t be bothered to try another font.&amp;nbsp; But for me, I want my font to speak to me a little.&amp;nbsp; But enough of that voodoo magic stuff.&lt;/p&gt; &lt;p&gt;The problem with sites that survey fonts is that it’s hard to compare quickly one with the next.&amp;nbsp; For example, this excellent article comparing &lt;a href="http://www.codeproject.com/KB/work/FontSurvey.aspx"&gt;42 fonts&lt;/a&gt; on CodeProject is one of the most comprehensive surveys, but even with that I can’t really tell if I prefer one font over another.&amp;nbsp; So, since I’m going to be doing this from time to time, I wrote a quick WPF app.&lt;/p&gt; &lt;p&gt;The XAML is simple, only this:&lt;/p&gt;&lt;pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;StackPanel&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Orientation&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;"Horizontal"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;ListBox&lt;/span&gt; &lt;span style="color: #ff0000"&gt;IsSynchronizedWithCurrentItem&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;"True"&lt;/span&gt; 
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;           &lt;span style="color: #ff0000"&gt;SelectedItem&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;"{Binding CurrentFont}"&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;           &lt;span style="color: #ff0000"&gt;ItemsSource&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;"{Binding Fonts}"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;TextBlock&lt;/span&gt; &lt;span style="color: #ff0000"&gt;FontFamily&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;'{Binding CurrentFont}'&lt;/span&gt; &lt;span style="color: #ff0000"&gt;FontSize&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;"14"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Text&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;"{Binding Code}"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;StackPanel&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/pre&gt;
&lt;p&gt;And the code is just as simple, only this:&lt;/p&gt;&lt;pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ViewModel
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;{
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; DependencyProperty CurrentFontProperty = DependencyProperty.Register("&lt;span style="color: #8b0000"&gt;CurrentFont&lt;/span&gt;", &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(FontFamily), &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(ViewModel));
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; FontFamily CurrentFont
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;get&lt;/span&gt; { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; (FontFamily)GetValue(CurrentFontProperty); }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;set&lt;/span&gt; { SetValue(CurrentFontProperty, &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;); }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; List&amp;lt;FontFamily&amp;gt; Fonts { &lt;span style="color: #0000ff"&gt;get&lt;/span&gt;; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;set&lt;/span&gt;; }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Code { &lt;span style="color: #0000ff"&gt;get&lt;/span&gt; { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; "&lt;span style="color: #8b0000"&gt;insert what you want to see&lt;/span&gt;"; } }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ViewModel()
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    Fonts = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; List&amp;lt;FontFamily&amp;gt;();
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    Fonts.AddRange(System.Windows.Media.Fonts.SystemFontFamilies);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;}&lt;/pre&gt;&lt;/pre&gt;
&lt;p&gt;And with this, you get something like this.&amp;nbsp; The coding sample is taken from &lt;a href="http://www.codinghorror.com/blog/2007/10/revisiting-programming-fonts.html"&gt;Coding Horror&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_WZr-_wsEf1c/Tca7-XGu9hI/AAAAAAAAADg/tMTpN66ytCU/s1600-h/image%5B8%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_WZr-_wsEf1c/Tca7-v3TvHI/AAAAAAAAADk/3uSZ9J1z5mk/image_thumb%5B4%5D.png?imgmax=800" width="644" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yep, my current chosen font is &lt;a href="http://www.fontsquirrel.com/fonts/BPmono"&gt;BPMono&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For the lazy, here’s the project on &lt;a href="https://github.com/bling/FontSampler"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-3566176541537863901?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/3566176541537863901/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=3566176541537863901' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/3566176541537863901'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/3566176541537863901'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2011/05/simple-app-to-preview-fonts.html' title='Simple App to Preview Fonts'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_WZr-_wsEf1c/Tca7-v3TvHI/AAAAAAAAADk/3uSZ9J1z5mk/s72-c/image_thumb%5B4%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-7704605337312479437</id><published>2011-04-17T13:22:00.001-07:00</published><updated>2011-04-17T13:22:31.404-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Tools'/><title type='text'>Integrating DependencyPropertyWeaver Into Your Build</title><content type='html'>&lt;p&gt;See the &lt;a href="http://blingcode.blogspot.com/2011/04/introducing-dependencypropertyweaver.html"&gt;introduction&lt;/a&gt; here.&lt;/p&gt; &lt;p&gt;The MSBuild task as it stands currently by default will attempt to weave everything that it finds.&amp;nbsp; This is probably not optimal in most use cases, but any changes is a simple modification to the LINQ query in the code.&amp;nbsp; For now, it’s only available in source format since there are bound to be bugs here and there, and once those get ironed out it’ll be easier to release a “point something” release.&lt;/p&gt; &lt;p&gt;An example of how its used can be seen in the unit tests, in the project DependencyPropertyWeaver.Tests.Models.&amp;nbsp; If you open it up in your favorite text editor, you will see this crucial line:&lt;/p&gt;&lt;pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Target&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Name&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;"AfterBuild"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Exec&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Command&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;"C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe postbuild.proj /p:Files=DependencyPropertyWeaver.Tests.Models.dll"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;WorkingDirectory&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;"$(OutputPath)"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Target&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/pre&gt;
&lt;p&gt;And the contents of &lt;em&gt;postbuild.proj&lt;/em&gt; is simply this:&lt;/p&gt;&lt;pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;?&lt;/span&gt;xml version="1.0" encoding="utf-8"&lt;span style="color: #0000ff"&gt;?&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Project&lt;/span&gt; &lt;span style="color: #ff0000"&gt;ToolsVersion&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;"4.0"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;DefaultTargets&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;"Weave"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlns&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;"http://schemas.microsoft.com/developer/msbuild/2003"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;UsingTask&lt;/span&gt; &lt;span style="color: #ff0000"&gt;TaskName&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;"DependencyPropertyWeaver.DependencyPropertyWeaverTask"&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;             &lt;span style="color: #ff0000"&gt;AssemblyFile&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;"DependencyPropertyWeaver.dll"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Target&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Name&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;"Weave"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;ItemGroup&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;      &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;Input&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Include&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;"$(Files)"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;ItemGroup&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;DependencyPropertyWeaverTask&lt;/span&gt; &lt;span style="color: #ff0000"&gt;Files&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;"@(Input)"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Target&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;Project&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;em&gt;AfterBuild&lt;/em&gt; target is a special target with MSBuild, which, as the name implies, will run after the target has been built.&amp;nbsp; In this case, after the project is completed, it will invoke another MSBuild instance to perform the weaving.&amp;nbsp; Invoking a new MSBuild process is required because the &amp;lt;UsingTask&amp;gt; will load the assembly into the current AppDomain, and once loaded it cannot be unloaded.&lt;/p&gt;
&lt;p&gt;If you don’t mind the unloading part, you can simply add the &amp;lt;UsingTask&amp;gt; directly into the project file and invoked the &amp;lt;DependencyPropertyWeaverTask&amp;gt; there, and avoid the hassle of having a separate file.&lt;/p&gt;
&lt;p&gt;Currently, the DependencyPropertyWeaverTask supports the &lt;em&gt;TypePatternMatch&lt;/em&gt; and &lt;em&gt;AttributePatternMatch&lt;/em&gt;, which as the names imply will use regular expression filtering on type names or properties with the attribute you want to weave.&amp;nbsp; If these properties are null, they are ignored.&lt;/p&gt;
&lt;p&gt;Next on the feature list is weaving attached properties ;-)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-7704605337312479437?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/7704605337312479437/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=7704605337312479437' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/7704605337312479437'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/7704605337312479437'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2011/04/integrating-dependencypropertyweaver.html' title='Integrating DependencyPropertyWeaver Into Your Build'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-192750451907354380</id><published>2011-04-15T19:09:00.001-07:00</published><updated>2011-04-15T19:18:21.540-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><title type='text'>Introducing DependencyPropertyWeaver</title><content type='html'>&lt;p&gt;As part of my demonstration for the NYC .NET Meetup in the next couple of days, I prepared some material to show how to use Mono.Cecil to manually weave IL as a post-build step.&amp;nbsp; It solves the problem of what I call “WPF Verbosity Hell”: the thing that makes your eyes bleed and makes God kill a kitten every time you declare a new property.&lt;/p&gt; &lt;p&gt;Since &lt;a href="http://code.google.com/p/notifypropertyweaver/"&gt;notifypropertyweaver&lt;/a&gt; already exists, I figured I’d release the other side of the coin, dependencypropertyweaver.&amp;nbsp; I just pushed my changes onto &lt;a href="https://github.com/bling/dependencypropertyweaver"&gt;GitHub&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;There are a couple of reasons to use dependency properties rather than regular properties with INotifyPropertyChanged.&amp;nbsp; If you’re using WPF they make more sense because they perform faster and they give you a lot of extra bells and whistles for free.&amp;nbsp; However, the INPC route tends to be more popular because it doesn’t bring in the dependency of WPF.&lt;/p&gt; &lt;p&gt;IL post-build weaving solves the dependency problem because you can selectively choose to weave only the assemblies that get deployed with WPF, and you could even weave INPC into your service layer, and DPs into your client layer.&amp;nbsp; That’s the power of post-build processes.&lt;/p&gt; &lt;p&gt;While this little project initially started out as a simple demonstration of using &lt;a href="http://www.mono-project.com/Cecil"&gt;Mono.Cecil&lt;/a&gt; to perform low-level aspect oriented principles, it didn’t take much more work to tidy things up and make it ‘releasable’ into the wild, so I did just that, and open sourced it.&lt;/p&gt; &lt;p&gt;The concept is simple.&amp;nbsp; You take something like this:&lt;/p&gt;&lt;pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Student
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Name { &lt;span style="color: #0000ff"&gt;get&lt;/span&gt;; &lt;span style="color: #0000ff"&gt;set&lt;/span&gt;; }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; Age { &lt;span style="color: #0000ff"&gt;get&lt;/span&gt;; &lt;span style="color: #0000ff"&gt;set&lt;/span&gt;; }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    }&lt;/pre&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;And DependencyPropertyWeaver will turn it into this:&lt;/p&gt;&lt;pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Student : DependencyObject
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;	{
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;		&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; DependencyProperty NameDependencyProperty = DependencyProperty.Register("&lt;span style="color: #8b0000"&gt;Name&lt;/span&gt;", &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;), &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(Student));
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;		&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; DependencyProperty AgeDependencyProperty = DependencyProperty.Register("&lt;span style="color: #8b0000"&gt;Age&lt;/span&gt;", &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;), &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(Student));
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;		&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Name
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;		{
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;			[CompilerGenerated]
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;			&lt;span style="color: #0000ff"&gt;get&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;			{
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;				&lt;span style="color: #0000ff"&gt;return&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;)&lt;span style="color: #0000ff"&gt;base&lt;/span&gt;.GetValue(Student.NameDependencyProperty);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;			}
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;			[CompilerGenerated]
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;			&lt;span style="color: #0000ff"&gt;set&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;			{
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;				&lt;span style="color: #0000ff"&gt;base&lt;/span&gt;.SetValue(Student.NameDependencyProperty, &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;			}
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;		}
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;		&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; Age
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;		{
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;			[CompilerGenerated]
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;			&lt;span style="color: #0000ff"&gt;get&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;			{
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;				&lt;span style="color: #0000ff"&gt;return&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;)&lt;span style="color: #0000ff"&gt;base&lt;/span&gt;.GetValue(Student.AgeDependencyProperty);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;			}
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;			[CompilerGenerated]
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;			&lt;span style="color: #0000ff"&gt;set&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;			{
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;				&lt;span style="color: #0000ff"&gt;base&lt;/span&gt;.SetValue(Student.AgeDependencyProperty, &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;			}
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;		}
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;	}&lt;/pre&gt;&lt;/pre&gt;
&lt;p&gt;Even though the class initially didn’t inherit from DependencyObject, the weaved version does.&amp;nbsp; It will also continually go up the inheritance chain until it finds the abstract base class, and makes that inherit from DependencyObject.&lt;/p&gt;
&lt;p&gt;Next on the list is obviously documentation (what open source project doesn’t need more documentation?!), however, I think I can slack off on this one since the core library is only 200-300 lines of code :-)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-192750451907354380?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/192750451907354380/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=192750451907354380' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/192750451907354380'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/192750451907354380'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2011/04/introducing-dependencypropertyweaver.html' title='Introducing DependencyPropertyWeaver'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-3518053343433815022</id><published>2011-03-10T19:38:00.001-08:00</published><updated>2011-03-10T19:38:53.576-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><title type='text'>That Commenting Thing</title><content type='html'>&lt;p&gt;I’m working on a project right now that has near 99% of its code commented.&amp;nbsp; Wow, that’s impressive!&amp;nbsp; Actually, it’s more scary…even some of the private fields are commented….&lt;/p&gt; &lt;p&gt;At one point, someone decided that it was a good idea to impose &lt;em&gt;some&lt;/em&gt; kind of standard rather than none, so they recommended &lt;a href="http://archive.msdn.microsoft.com/sourceanalysis"&gt;StyleCop&lt;/a&gt; with all of its default settings, including requiring comments on everything.&lt;/p&gt; &lt;p&gt;This seemed like a good idea, and it probably was, until someone found &lt;a href="http://submain.com/products/ghostdoc.aspx"&gt;GhostDoc&lt;/a&gt;.&amp;nbsp; The plugin definitely gives off that “cool” factor the first time you use it.&amp;nbsp; Wow, with a single key stroke it automagically documented all of my code!!!&amp;nbsp; The problem, and it’s a pretty big one, is that it generates documentation based on the name of the properties, names, and class.&amp;nbsp; Surely if it can do that, you, a much more sophisticated machine, can do that!&lt;/p&gt; &lt;p&gt;Alas, the code base ended up getting GhostDocced to death all over the place to the point where I was driven mad and insane that I spent the time to write a VS2010 extension to purposely hide these comments.&amp;nbsp; I’m talking about comments like this:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_WZr-_wsEf1c/TXmZSvlTRnI/AAAAAAAAADQ/hk3vTlVJ5Jc/s1600-h/image%5B4%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_WZr-_wsEf1c/TXmZSurQc8I/AAAAAAAAADU/NCeYxDgaINc/image_thumb%5B2%5D.png?imgmax=800" width="505" height="156"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The comments add absolutely &lt;strong&gt;no value&lt;/strong&gt; and IMO &lt;strong&gt;makes it harder to read&lt;/strong&gt;, and has the added deficit that if for whatever reason someone changes the name property, chances are they will forget to update the comments.&amp;nbsp; It gets worse with WCF service contracts with many parameters.&lt;/p&gt; &lt;p&gt;So yes, it frustrated me enough that I took some spare time to write an extension to shrink those damn XML comments to such a small size it doesn’t bother me anymore, like this:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_WZr-_wsEf1c/TXmZS7pHAXI/AAAAAAAAADY/IV53KxtUWUQ/s1600-h/image%5B8%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_WZr-_wsEf1c/TXmZTTUjF0I/AAAAAAAAADc/h96-4zUY6oM/image_thumb%5B4%5D.png?imgmax=800" width="566" height="200"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;You can grab the code off &lt;a href="https://github.com/bling/XmlCommentShrink"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-3518053343433815022?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/3518053343433815022/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=3518053343433815022' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/3518053343433815022'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/3518053343433815022'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2011/03/that-commenting-thing.html' title='That Commenting Thing'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_WZr-_wsEf1c/TXmZSurQc8I/AAAAAAAAADU/NCeYxDgaINc/s72-c/image_thumb%5B2%5D.png?imgmax=800' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-3134692404221036146</id><published>2010-12-11T15:59:00.001-08:00</published><updated>2010-12-11T16:00:59.030-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Castle'/><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><title type='text'>Auto Mocking NSubstitute with Castle Windsor</title><content type='html'>&lt;p&gt;I was debating whether to make this blog post because it’s so damn simple to implement, but hey, if it saves someone else time, I did some good.&lt;/p&gt; &lt;p&gt;First of all, register an ILazyComponentLoader into Windsor:&lt;/p&gt;&lt;pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;var c = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; WindsorContainer();
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;c.Register(Component.For&amp;lt;LazyComponentAutoMocker&amp;gt;());&lt;/pre&gt;&lt;/pre&gt;
&lt;p&gt;Then, the implementation of LazyComponentAutoMocker is simply this:&lt;/p&gt;&lt;pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; LazyComponentAutoMocker : ILazyComponentLoader
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;{
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; IRegistration Load(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; key, Type service, IDictionary arguments)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; Component.For(service).Instance(Substitute.For(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt;[] { service }, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;));
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;}&lt;/pre&gt;&lt;/pre&gt;
&lt;p&gt;And you’re done!&amp;nbsp; Here’s a simple unit test example using &lt;strong&gt;only&lt;/strong&gt; the code from above:&lt;/p&gt;&lt;pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;[Test]
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; IDictionary_Add_Invoked()
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;{
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  var dict = c.Resolve&amp;lt;IDictionary&amp;gt;();
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  dict.Add(1, 1);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  dict.Received().Add(1, 1);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;}&lt;/pre&gt;&lt;/pre&gt;
&lt;p&gt;That was almost too easy.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-3134692404221036146?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/3134692404221036146/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=3134692404221036146' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/3134692404221036146'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/3134692404221036146'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2010/12/auto-mocking-nsubstitute-with-castle.html' title='Auto Mocking NSubstitute with Castle Windsor'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-1225817398712680345</id><published>2010-12-05T14:17:00.001-08:00</published><updated>2010-12-05T17:43:41.803-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Source Control Management'/><title type='text'>Working in Git to Working in Mercurial</title><content type='html'>&lt;p&gt;I took the dive a couple weeks ago and learned how to use Git and fell in love with its simplicity.&amp;nbsp; I don’t know what it is, but after using Git every day it actually started to &lt;em&gt;make sense&lt;/em&gt; that &lt;strong&gt;git checkout &lt;/strong&gt;is used for so many things, which is ironic because prior to using Git, every introductory tutorial I’ve read has always had me thinking, “checkout does what and what and what now??”.&lt;/p&gt; &lt;p&gt;So why did I switch to Mercurial?&amp;nbsp; I need to push/pull from a Subversion repository, and I work on Windows.&amp;nbsp; General day to day work is great, but when I needed to &lt;strong&gt;git svn rebase&lt;/strong&gt; or &lt;strong&gt;git svn dcommit&lt;/strong&gt; it would take so long that I simply left to get coffee.&amp;nbsp; What’s worse, no matter what I set for core.autocrlf I would &lt;em&gt;always&lt;/em&gt; get some weird whitespace merging error, when nothing was wrong.&amp;nbsp; It became a regular part of my workflow to just &lt;strong&gt;git rebase –skip&lt;/strong&gt; everything because that’s what fixed things.&amp;nbsp; Scary.&lt;/p&gt; &lt;p&gt;The crappy Subversion and whitespace support (at least in Windows) led me to try Mercurial.&amp;nbsp; After getting accustomed to Mercurial, they’re actually a lot more similar than they are different.&lt;/p&gt; &lt;p&gt;First things first, you need to add the following to your mercurial.ini file in your home directory:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;[bookmarks]&lt;br&gt;track.current = True&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Here’s a comparison of my typical Git workflow translated to Mercurial:&lt;/p&gt; &lt;table border="1" cellspacing="0" cellpadding="2" width="600"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="201"&gt;&amp;nbsp;&lt;/td&gt; &lt;td valign="top" width="199"&gt;&lt;strong&gt;Git&lt;/strong&gt;&lt;/td&gt; &lt;td valign="top" width="198"&gt;&lt;strong&gt;Mercurial&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="201"&gt;Work on a new feature/bug&lt;/td&gt; &lt;td valign="top" width="199"&gt;git checkout –b new_feature&lt;/td&gt; &lt;td valign="top" width="198"&gt;hg book new_feature&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="201"&gt;Hack hack hack&lt;/td&gt; &lt;td valign="top" width="199"&gt;git add .&lt;/td&gt; &lt;td valign="top" width="198"&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="201"&gt;Commit&lt;/td&gt; &lt;td valign="top" width="199"&gt;git commit –m “done!”&lt;/td&gt; &lt;td valign="top" width="198"&gt;hg commit –m “done!”&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="201"&gt;Hack more and commit&lt;/td&gt; &lt;td valign="top" width="199"&gt;git commit –a –m “more hacking”&lt;/td&gt; &lt;td valign="top" width="198"&gt;hg commit –m “more hacking”&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="201"&gt;Sync with up stream&lt;/td&gt; &lt;td valign="top" width="199"&gt;git pull master&lt;/td&gt; &lt;td valign="top" width="198"&gt;hg pull&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="201"&gt;Merge&lt;/td&gt; &lt;td valign="top" width="199"&gt;git checkout master&lt;/td&gt; &lt;td valign="top" width="198"&gt;hg merge new_feature&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="201"&gt;&amp;nbsp;&lt;/td&gt; &lt;td valign="top" width="199"&gt;git merge new_feature&lt;/td&gt; &lt;td valign="top" width="198"&gt;hg commit –m “merged”&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="201"&gt;Push&lt;/td&gt; &lt;td valign="top" width="199"&gt;git push&lt;/td&gt; &lt;td valign="top" width="198"&gt;hg push&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;Notice that they’re practically exactly the same?&amp;nbsp; There are some minor differences.&amp;nbsp; The obvious one being that you need to add into git’s index before committing.&amp;nbsp; And the other I didn’t have to switch branches in Mercurial (more on that later).&amp;nbsp; But aside from that, it’s pretty much the same, &lt;strong&gt;from a user’s point of view&lt;/strong&gt;.&amp;nbsp; Check this fantastic &lt;a href="http://stackoverflow.com/questions/1598759/git-and-mercurial-compare-and-contrast"&gt;thread&lt;/a&gt; on StackOverflow for one of the best comparisons on the net if you want to dive into technical details.&lt;/p&gt; &lt;p&gt;So far, there are only two things that bother me having switched:&lt;br&gt;&amp;nbsp; a) No fast-forward merge.&amp;nbsp; You need to manually rebase and then commit.&lt;br&gt;&amp;nbsp; b) No automatic commit after a conflict free merge.&lt;/p&gt; &lt;p&gt;These are fairly minor annoyances, but can be scripted/aliased away.&amp;nbsp; Or if you don’t like those defaults in Git, you can override them in the command arguments or set them in gitconfig.&amp;nbsp; Mercurial similarly can change default arguments in its hgrc/mercurial.ini.&lt;/p&gt; &lt;p&gt;One of the biggest advantages of Git is easily switching between all its local lightweight branches at lightning speed.&amp;nbsp; Tangled source code is no more!&amp;nbsp; I was confused with Mercurial’s bookmarks when I first used them because all it does is label your head with something.&amp;nbsp; I don’t know why this is, but it is the same as &lt;strong&gt;git checkout –b&lt;/strong&gt;, but for some reason I visualized Git “branching” the latest commit into two paths.&amp;nbsp; But how do you do that if they’re the same?&amp;nbsp; It should only branch &lt;em&gt;after&lt;/em&gt; a commit which introduces changes, which is what Mercurial does.&amp;nbsp; In this scenario, Mercurial is more explicit, whereas Git is implicit.&lt;/p&gt; &lt;p&gt;Using bookmarks, you can mimic Git’s workflow like this:&lt;/p&gt; &lt;table border="1" cellspacing="0" cellpadding="2" width="594"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="209"&gt;&amp;nbsp;&lt;/td&gt; &lt;td valign="top" width="192"&gt;&lt;strong&gt;Git&lt;/strong&gt;&lt;/td&gt; &lt;td valign="top" width="191"&gt;&lt;strong&gt;Mercurial&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="212"&gt;Create a bunch of ‘working areas’&lt;/td&gt; &lt;td valign="top" width="190"&gt;git branch feature1&lt;/td&gt; &lt;td valign="top" width="189"&gt;hg book feature1&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="214"&gt;&amp;nbsp;&lt;/td&gt; &lt;td valign="top" width="190"&gt;git branch feature2&lt;/td&gt; &lt;td valign="top" width="189"&gt;hg book feature2&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="216"&gt;Switch/commit/hack/commit&lt;/td&gt; &lt;td valign="top" width="189"&gt;git checkout feature1&lt;/td&gt; &lt;td valign="top" width="188"&gt;hg up feature1&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="217"&gt;&amp;nbsp;&lt;/td&gt; &lt;td valign="top" width="189"&gt;git commit –a –m “feature1”&lt;/td&gt; &lt;td valign="top" width="188"&gt;hg commit –m “feature1”&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="218"&gt;&amp;nbsp;&lt;/td&gt; &lt;td valign="top" width="188"&gt;git checkout feature2&lt;/td&gt; &lt;td valign="top" width="187"&gt;hg up feature2&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="219"&gt;&amp;nbsp;&lt;/td&gt; &lt;td valign="top" width="188"&gt;git commit –a –m “feature1”&lt;/td&gt; &lt;td valign="top" width="187"&gt;hg commit –m “feature2”&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="219"&gt;Sync up stream&lt;/td&gt; &lt;td valign="top" width="188"&gt;git pull master&lt;/td&gt; &lt;td valign="top" width="187"&gt;hg pull&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="219"&gt;&amp;nbsp;&lt;/td&gt; &lt;td valign="top" width="188"&gt;git checkout master&lt;/td&gt; &lt;td valign="top" width="187"&gt;hg up default&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="219"&gt;Merge in 1 feature&lt;/td&gt; &lt;td valign="top" width="188"&gt;git merge feature1&lt;/td&gt; &lt;td valign="top" width="187"&gt;hg merge feature1&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="219"&gt;&amp;nbsp;&lt;/td&gt; &lt;td valign="top" width="188"&gt;&amp;nbsp;&lt;/td&gt; &lt;td valign="top" width="187"&gt;hg commit –m “merged”&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="219"&gt;Delete branch/bookmark&lt;/td&gt; &lt;td valign="top" width="188"&gt;git branch –d feature1&lt;/td&gt; &lt;td valign="top" width="187"&gt;hg book –d feature1&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="219"&gt;Push&lt;/td&gt; &lt;td valign="top" width="188"&gt;git push&lt;/td&gt; &lt;td valign="top" width="187"&gt;hg push –r tip&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="219"&gt;Switch back and hack again&lt;/td&gt; &lt;td valign="top" width="188"&gt;git checkout feature2&lt;/td&gt; &lt;td valign="top" width="188"&gt;hg up feature2&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;The &lt;strong&gt;–r tip&lt;/strong&gt; switch on hg push might have raised an eyebrow.&amp;nbsp; This is to tell Mercurial to push all changes that lead to the tip.&amp;nbsp; This will include the changes in &lt;em&gt;feature1&lt;/em&gt; that we just merged in, but exclude all the ones in &lt;em&gt;feature2&lt;/em&gt;.&amp;nbsp; If you issue a &lt;strong&gt;hg push&lt;/strong&gt; it will complain and warn you that you’re going to create multiple heads on the remote repository.&amp;nbsp; This is not what you want since there may be unfinished features, experimental branches, etc.&amp;nbsp; Of course, you can force it anyways, but that’s not a good idea.&lt;/p&gt; &lt;p&gt;At first, the tip was most confusing to me because I tried to associate it with Git’s master, which was simply not the case.&amp;nbsp; Tip refers to the newest change that you know about.&amp;nbsp; This can be on any branch or bookmark.&amp;nbsp; Once I understood that, and &lt;strong&gt;stopped trying to create a Git master&lt;/strong&gt; equivalent, everything was straightforward.&lt;/p&gt; &lt;p&gt;So let’s start with an example.&amp;nbsp; First I create a bookmark &lt;em&gt;feature1&lt;/em&gt; after syncing, and then making a commit looks like this: &lt;/p&gt; &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_WZr-_wsEf1c/TPwPhlbcWDI/AAAAAAAAACo/3_P3Zvqu1pM/s1600-h/image%5B2%5D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: ; 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/_WZr-_wsEf1c/TPwPiMwJxgI/AAAAAAAAACs/DmZxxuMAb2k/image_thumb.png?imgmax=800" width="238" height="101"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;And then if you switch to &lt;em&gt;feature2&lt;/em&gt; and make a commit, it becomes like this:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_WZr-_wsEf1c/TPwPiUVV5WI/AAAAAAAAACw/9lf6dwKGApg/s1600-h/image%5B5%5D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: ; 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/_WZr-_wsEf1c/TPwPi48MmdI/AAAAAAAAAC0/cC_c0bvyvis/image_thumb%5B1%5D.png?imgmax=800" width="243" height="124"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Here’s where you start thinking, “I don’t have a master which tracks upstream changes, how do I separate my local changes?”&amp;nbsp; And now here’s a situation where Mercurial does more black magic than Git.&amp;nbsp; If there are up stream changes, after issuing &lt;strong&gt;hg pull&lt;/strong&gt;, this happens:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_WZr-_wsEf1c/TPwPjPEMdfI/AAAAAAAAAC4/f2d3b4qfeCE/s1600-h/image%5B8%5D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: ; 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/_WZr-_wsEf1c/TPwPjRxmonI/AAAAAAAAAC8/IrEz8ig5Zo0/image_thumb%5B2%5D.png?imgmax=800" width="244" height="144"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Mercurial automatically split my local changes into their own separate branches (actually, &lt;em&gt;heads&lt;/em&gt; is the accurate term).&amp;nbsp; After this operation, &lt;strong&gt;tip&lt;/strong&gt; is now tracking the changes that I just pulled in from upstream, instead of my bookmark.&lt;/p&gt; &lt;p&gt;From here, it’s simply &lt;strong&gt;hg up tip&lt;/strong&gt; to switch to the “master” branch.&amp;nbsp; Then a &lt;strong&gt;hg merge feature1; hg commit&lt;/strong&gt;, and it becomes like this:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_WZr-_wsEf1c/TPwPjoJRV0I/AAAAAAAAADA/PEV6bis7pJg/s1600-h/image%5B11%5D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: ; 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/_WZr-_wsEf1c/TPwPkIS-mgI/AAAAAAAAADE/labU8QL9AKQ/image_thumb%5B3%5D.png?imgmax=800" width="244" height="168"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Then it’s simply &lt;strong&gt;hg push –r tip&lt;/strong&gt;, and you’re good to go.&amp;nbsp; Basically, if you bookmark every feature/bug you work on, then you should only have one branch that doesn’t have a bookmark, which is the same as the ‘master’ branch from Git.&lt;/p&gt; &lt;h4&gt;What about Subversion?&lt;/h4&gt; &lt;p&gt;Whoops, forgot why I switched in the first place.&amp;nbsp; First, install &lt;a href="http://bitbucket.org/durin42/hgsubversion/wiki/Home"&gt;hgsubversion&lt;/a&gt;, after that’s set up, simply:&lt;/p&gt; &lt;p&gt;hg clone &lt;a href="http://path/to/subversion/repository"&gt;http://path/to/subversion/repository&lt;/a&gt;&lt;/p&gt; &lt;p&gt;And then it’s just &lt;strong&gt;hg pull&lt;/strong&gt; or &lt;strong&gt;hg push&lt;/strong&gt;.&amp;nbsp; Is it really that simple?&amp;nbsp; Yes, yes it is.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-1225817398712680345?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/1225817398712680345/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=1225817398712680345' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/1225817398712680345'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/1225817398712680345'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2010/12/working-in-git-to-working-in-mercurial.html' title='Working in Git to Working in Mercurial'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_WZr-_wsEf1c/TPwPiMwJxgI/AAAAAAAAACs/DmZxxuMAb2k/s72-c/image_thumb.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-8337332379723295644</id><published>2010-12-04T14:46:00.001-08:00</published><updated>2010-12-05T19:49:57.867-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><category scheme='http://www.blogger.com/atom/ns#' term='CQRS'/><title type='text'>CQRS: Building a “Transactional” Event Store with MongoDB</title><content type='html'>&lt;p&gt;As you all already know if you’re familiar with MongoDB, is that it does not support transactions.&amp;nbsp; The closest thing we have is atomic modifications of a single document.&lt;/p&gt; &lt;p&gt;The Event Store in a CQRS architecture has the important responsibility of detecting concurrency violations, where two different sources try to update the same version of the aggregate.&amp;nbsp; The one that gets it late should be denied changes into the store with an exception thrown.&amp;nbsp; This ensures the integrity of the data.&lt;/p&gt; &lt;p&gt;Here is a very simple typical implementation of appending events into the event store:&lt;/p&gt;&lt;pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Append(Guid id, &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; expectedVersion, IEnumerable&amp;lt;IEvent&amp;gt; events)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;{
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&amp;nbsp; &lt;span style="color: #0000ff"&gt;try&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&amp;nbsp; {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _events.Insert(events.Select(x =&amp;gt; ...)); &lt;span style="color: #008000"&gt;// convert to storage type&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&amp;nbsp; }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&amp;nbsp; &lt;span style="color: #0000ff"&gt;catch&lt;/span&gt; (...)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&amp;nbsp; {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&amp;nbsp; &lt;span style="color: #0000ff"&gt;&amp;nbsp; if&lt;/span&gt; (E11000 duplicate key)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&amp;nbsp; &lt;span style="color: #0000ff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ConcurrencyException(...);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&amp;nbsp; }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;}&lt;/pre&gt;&lt;/pre&gt;
&lt;p&gt;Syntax is a mix of C#/pseudo code, but the basic concepts are the same.&amp;nbsp; This assumes that you’ve set up an multi-index on the collection between the ID and the version.&amp;nbsp; Thus, when you insert something that already has a matching ID/version, Mongo will tell you of a duplicate key violation, and all is good.&lt;/p&gt;
&lt;p&gt;But wait!&amp;nbsp; Operations are atomic per document!&amp;nbsp; So what happens if you append 100 events, and it fails on the 43rd one?&amp;nbsp; Events 1 through 42 will continue to exist in the data store, which is bad news.&lt;/p&gt;
&lt;p&gt;Obviously, this solution is not going to work.&amp;nbsp; The next step was to do something like this:&lt;/p&gt;&lt;pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;catch&lt;/span&gt; (...)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;{
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;&amp;nbsp; if&lt;/span&gt; (E11000 duplicate keys)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&amp;nbsp; {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach&lt;/span&gt; (var e &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; events)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _events.Delete(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; { _id = e._id });
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ConcurrencyException(...);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&amp;nbsp; }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;}&lt;/pre&gt;&lt;/pre&gt;
&lt;p&gt;So, before inserting into the collection, each events gets a generated ObjectID, so that if it fails, the catch exception can simply tell the data store to delete everything.&lt;/p&gt;
&lt;p&gt;At first glance this seems to fix everything, except for one glaring problem.&amp;nbsp; What happens if you lose connection to the database before, or midway sending the deletes?&amp;nbsp; Now you have a problem of &lt;strong&gt;ensuring&lt;/strong&gt; that those deletes are guaranteed, and so then the question that arises from that is &lt;strong&gt;where&lt;/strong&gt; would you store it?&amp;nbsp; A local file?&amp;nbsp; Another database?&amp;nbsp; The problem is, at that moment, if another process in the system queries all events for the same aggregate it will return invalid data.&lt;/p&gt;
&lt;p&gt;So, we’re back to square one.&amp;nbsp; We need to simulate a transaction through a single insert.&lt;/p&gt;
&lt;p&gt;The secret is in the schema design.&amp;nbsp; Initially, we started out with a straight forward row-per-event schema.&amp;nbsp; But since we’re operating with &lt;em&gt;documents&lt;/em&gt;, we can model it as a &lt;em&gt;batch&lt;/em&gt; of events.&lt;/p&gt;
&lt;p&gt;Thus, instead of versioning every event individually, we version a batch of events.&amp;nbsp; For example, originally we would insert 3 events, and the data saved would look like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;{ _id = 1, aggregate_id = 1, version = 1, event = { … } }&lt;br&gt;{ _id = 2, aggregate_id = 1, version = 2, event = { … } }&lt;br&gt;{ _id = 3, aggregate_id = 1, version = 3, event = { … } }&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;In the new schema, it would look like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;{ _id = 1, aggregate_id = 1, version = 1, &lt;strong&gt;events&lt;/strong&gt; = [ { … }, { … }, { … }, { … } ] }&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Now, a downside to this approach is you lose a bit of granularity of stored events, since you are grouping multiple events under a single version.&amp;nbsp; However, I don’t see this as a huge loss since the main reason you want to use event sourcing in the first place is to be able to restore an aggregate to any state in its history, and we still retain that functionality.&lt;/p&gt;
&lt;p&gt;In our case, this is working very well for us.&amp;nbsp; When a command gets handled, it generates a bunch of events that get applied and then saved to MongoDB.&amp;nbsp; I can’t think of any scenario where it’d want to replay to the middle of a half-processed command (but of course it’s possible anyways, just reply half of a batch of events).&amp;nbsp; But that’s just asking for trouble.&amp;nbsp; It’s most likely easier to just the re-process the command.&lt;/p&gt;
&lt;p&gt;Now, you may be asking why go through the trouble of batching events when you can just store one document per aggregate, and then put all events in one document?&amp;nbsp; Yes, that would solve the problem very effectively…until you hit the 4MB per document limit ;-)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-8337332379723295644?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/8337332379723295644/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=8337332379723295644' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/8337332379723295644'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/8337332379723295644'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2010/12/cqrs-building-transactional-event-store.html' title='CQRS: Building a “Transactional” Event Store with MongoDB'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-2160834794585854315</id><published>2010-11-23T20:46:00.000-08:00</published><updated>2010-12-05T20:46:31.329-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><category scheme='http://www.blogger.com/atom/ns#' term='CQRS'/><title type='text'>CQRS: Auto register event handlers</title><content type='html'>&lt;p&gt;I’m not going to go into detail about what the deal is about event handlers in a CQRS architecture, since a quick Google/Bing search will give plenty of very good information.&amp;nbsp; What this post is about is a solution to the “how do I quickly register something to handle a bunch of events” without copying pasting all over the place. There are other solutions out there, like &lt;a href="http://thinkbeforecoding.com/post/2009/11/03/Event-Sourcing-and-CQRS-Dispatch-options"&gt;this one&lt;/a&gt;.&amp;nbsp; Here’s something I came up with (took some concepts from my post on &lt;a href="http://blingcode.blogspot.com/2010/10/yet-another-weak-event-for-wpf.html"&gt;Weak Events&lt;/a&gt;).&lt;/p&gt;&lt;pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Aggregate
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;{
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;delegate&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; OpenEventHandler&amp;lt;&lt;span style="color: #0000ff"&gt;in&lt;/span&gt; TTarget, &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; TEvt&amp;gt;(TTarget target, TEvt @&lt;span style="color: #0000ff"&gt;event&lt;/span&gt;);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; IDictionary&amp;lt;Type, OpenEventHandler&amp;lt;Game, IEvent&amp;gt;&amp;gt; _evtHandlers = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Dictionary&amp;lt;Type, OpenEventHandler&amp;lt;Game, IEvent&amp;gt;&amp;gt;();
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;   
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; Aggregate()
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    var methods = from m &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(Game).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    let p = m.GetParameters()
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;            where m.Name == "&lt;span style="color: #8b0000"&gt;ApplyEvent&lt;/span&gt;" &amp;amp;&amp;amp; p.Length == 1 &amp;amp;&amp;amp; &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(IEvent).IsAssignableFrom(p[0].ParameterType)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;            select m;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    var registerForwarder = &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(Game).GetMethod("&lt;span style="color: #8b0000"&gt;RegisterForwarder&lt;/span&gt;", BindingFlags.NonPublic | BindingFlags.Static);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (var m &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; methods)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;      Type eventType = m.GetParameters()[0].ParameterType;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;      var forwarder = registerForwarder.MakeGenericMethod(eventType).Invoke(&lt;span style="color: #0000ff"&gt;null&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;new&lt;/span&gt;[] { m });
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;      _evtHandlers[eventType] = (OpenEventHandler&amp;lt;Game, IEvent&amp;gt;)forwarder;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; OpenEventHandler&amp;lt;Game, IEvent&amp;gt; RegisterForwarder&amp;lt;TEvt&amp;gt;(MethodInfo method)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    var invoker = &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(OpenEventHandler&amp;lt;,&amp;gt;).MakeGenericType(&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(Game), &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(TEvt));
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    var forwarder = (OpenEventHandler&amp;lt;Game, TEvt&amp;gt;)Delegate.CreateDelegate(invoker, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;, method);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; (g, e) =&amp;gt; forwarder(g, (TEvt)e);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt; 
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; ApplyEvent(EventHappened e)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    _something = e.Something;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt; 
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; ApplyChanges(IEnumerable&amp;lt;IEvent&amp;gt; events)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (var e &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; events)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;      _evtHandlers[e.GetType()](&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;, e);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;    }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;  }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"&gt;}&lt;/pre&gt;&lt;/pre&gt;
&lt;p&gt;A couple things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The registration happens in the &lt;strong&gt;static constructor&lt;/strong&gt;.&amp;nbsp; This is important, because this relatively heavy cost of using reflection only happens once for the aggregate. 
&lt;li&gt;The filtering of methods is arbitrary.&amp;nbsp; I chose “ApplyEvent” here as the convention, but of course you can choose whatever you like. 
&lt;li&gt;&lt;em&gt;ApplyChanges&lt;/em&gt; simply invokes the event handlers dictionary directly.&amp;nbsp; Assuming you’re being a good citizen with the code, accessing &lt;em&gt;_evtHandlers&lt;/em&gt; doesn’t need a lock because once created it should never be modified.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;So in summary, it finds all methods named &lt;em&gt;ApplyEvent&lt;/em&gt; in the current class, and generates an “open delegate” which takes in an extra parameter which is the instance itself.&amp;nbsp; In this case, the instance is the aggregate, as shown in the &lt;em&gt;ApplyChanges&lt;/em&gt; method.&lt;/p&gt;
&lt;p&gt;So there you have it!&amp;nbsp; Excluding the lengthy LINQ query, roughly 10 lines of code to find and register all event handlers in the aggregate.&amp;nbsp; And if you’re wondering, the performance cost is negligible because there’s no reflection involved in the invocation of the handlers.&amp;nbsp; Awesome!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-2160834794585854315?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/2160834794585854315/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=2160834794585854315' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/2160834794585854315'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/2160834794585854315'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2010/11/cqrs-auto-register-event-handlers.html' title='CQRS: Auto register event handlers'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-8266634622118380322</id><published>2010-11-07T21:43:00.001-08:00</published><updated>2010-12-05T17:52:10.786-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><title type='text'>That Immutable Thing</title><content type='html'>&lt;p&gt;Do you have some sort of ImmutableAttribute in your domain that you use to mark classes as immutable?&amp;#160; Have you ever needed to enforce that contract?&amp;#160; Checking for readonly fields isn’t enough?&amp;#160; Well, this weekend I had a code spike that helped solve this problem in my current project.&lt;/p&gt;  &lt;p&gt;For this project, I’m using the &lt;a href="http://normproject.org"&gt;NoRM&lt;/a&gt; driver for &lt;a href="http://www.mongodb.org/"&gt;MongoDB&lt;/a&gt;, and one of the limitations of the serializer is that all types must be classes, must have a default constructor, and all properties have a public setter.&amp;#160; So, now the domain has a bunch of classes like this:&lt;/p&gt;  &lt;pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; UserCreatedEvent : IEvent
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;{
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Name { &lt;span style="color: #0000ff"&gt;get&lt;/span&gt;; &lt;span style="color: #0000ff"&gt;set&lt;/span&gt;; }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; UserCreatedEvent() { }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; UserCreatedEvent(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; name) { Name = name; }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;}&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;That God for code snippets (or Resharper templates).&amp;#160; With so many classes like this that need to get serialized, I wanted to extra sure that no code ever calls the setter method for the Name property.&amp;#160; Thankfully, with some help of &lt;a href="https://github.com/jbevain/cecil"&gt;Mono.Cecil&lt;/a&gt;, it’s possible.&lt;/p&gt;
&lt;p&gt;First off, you need to define &lt;em&gt;ImmutableAttribute&lt;/em&gt; and that add that do classes, and in my case, it is historical domain events that get serialized to an event store.&lt;/p&gt;
&lt;p&gt;Then, you just write a unit test which leverages the power of Mono.Cecil.&amp;#160; It turned out to be pretty simple.&amp;#160; Here’s the code:&lt;/p&gt;

&lt;pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Collections.Generic;
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Linq;
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; Mono.Cecil;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; Mono.Cecil.Cil;
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; NUnit.Framework;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; blingcode
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;{
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    [TestFixture]
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ImmutabilityTests
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; MethodDefinition[] _setterMethods;
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; AssemblyDefinition[] _assemblies;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; ImmutabilityTests()
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            _assemblies = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt;[]
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                AssemblyDefinition.ReadAssembly(&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(Something).Assembly.Location),
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            };
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            _setterMethods = _assemblies
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                .SelectMany(a =&amp;gt; a.Modules)
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                .SelectMany(m =&amp;gt; m.Types)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                .Where(t =&amp;gt; t.CustomAttributes.Any(attr =&amp;gt; attr.AttributeType.Name.Contains(&amp;quot;&lt;span style="color: #8b0000"&gt;ImmutableAttribute&lt;/span&gt;&amp;quot;)))
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                .SelectMany(t =&amp;gt; t.Properties)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                .Where(p =&amp;gt; p.SetMethod != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                .Select(m =&amp;gt; m.SetMethod)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                .ToArray();
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        [Test]
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; ClassesWith_ImmutableAttribute_ShouldNotUse_PropertySetters()
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            AssertForViolations(_assemblies
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                                    .SelectMany(a =&amp;gt; a.Modules)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                                    .SelectMany(m =&amp;gt; m.Types)
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                                    .Where(t =&amp;gt; t.IsClass)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                                    .SelectMany(t =&amp;gt; t.Methods));
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        [Test]
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; ThisFixtureActuallyWorks()
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            var assembly = AssemblyDefinition.ReadAssembly(&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(ImmutabilityTests).Assembly.Location);
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            var type = assembly.Modules.SelectMany(m =&amp;gt; m.Types)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                .Where(t =&amp;gt; t.IsClass &amp;amp;&amp;amp; t.FullName.Contains(GetType().FullName)).First();
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;try&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                AssertForViolations(type.Methods);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;catch&lt;/span&gt; (AssertionException)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                Assert.Pass();
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; AssertForViolations(IEnumerable&amp;lt;MethodDefinition&amp;gt; potentialMethods)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (var method &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; potentialMethods.Where(m =&amp;gt; m.HasBody))
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (Instruction ins &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; method.Body.Instructions.Where(ins =&amp;gt; ins.OpCode == OpCodes.Callvirt))
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                    MemberReference mr = ins.Operand &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; MemberReference;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (mr != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                    {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                        var result = _setterMethods.FirstOrDefault(m =&amp;gt; m.FullName == mr.FullName);
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (result != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                        {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                            &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; AssertionException(result + &amp;quot;&lt;span style="color: #8b0000"&gt; was invoked by &lt;/span&gt;&amp;quot; + method + &amp;quot;&lt;span style="color: #8b0000"&gt;, even though the type has the Immutable attribute.&lt;/span&gt;&amp;quot;);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                        }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                    }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; InvokeCardSetters()
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #008000"&gt;// this only exists to test that the test does indeed work&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            var c = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; SomeImmutableClass();
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            c.SomeImmutableValue = 123;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;}&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Nothing too complicated.&amp;#160; The main thing to look for is the &lt;strong&gt;callvirt&lt;/strong&gt; method, which the C# compiler always generates for classes.&amp;#160; Then, you match the operand to the method definition and viola!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-8266634622118380322?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/8266634622118380322/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=8266634622118380322' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/8266634622118380322'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/8266634622118380322'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2010/11/that-immutable-thing.html' title='That Immutable Thing'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-9104676563589553908</id><published>2010-10-05T07:53:00.001-07:00</published><updated>2010-10-05T07:53:50.073-07:00</updated><title type='text'>Memory Leak with WPF’s RichTextBox</title><content type='html'>&lt;p&gt;Apparently, setting IsUndoEnabled to false isn’t enough.&amp;#160; You must also set UndoLimit=0 as well otherwise it’ll still keep track of undo history.&amp;#160; Doh!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-9104676563589553908?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/9104676563589553908/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=9104676563589553908' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/9104676563589553908'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/9104676563589553908'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2010/10/memory-leak-with-wpfs-richtextbox.html' title='Memory Leak with WPF’s RichTextBox'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-4113530620239179912</id><published>2010-10-04T00:06:00.001-07:00</published><updated>2010-10-04T00:21:55.549-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><title type='text'>Yet Another Weak Event Implementation</title><content type='html'>&lt;p&gt;I gotta say that WPF is a complete pain in the butt when it comes to memory leaks.&amp;#160; A simple google/bing search shows up more than enough results for weak events, so why am I making yet another blog post about another implementation of a weak event?&amp;#160; Well, if someone else out there happens to have the same requirements/needs that I do right now, maybe this will save them a little time.&lt;/p&gt;  &lt;p&gt;In my particular case, I needed to accomplish a couple goals:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Minimal performance hit.&amp;#160; a.k.a minimal use of reflection. &lt;/li&gt;    &lt;li&gt;Generic and easy to use. &lt;/li&gt;    &lt;li&gt;Thread safe. &lt;/li&gt;    &lt;li&gt;Support for explicit registration and unregistration. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;One of the better implementations on weak events I found was from Dustin Campbell’s &lt;a href="http://diditwith.net/PermaLink,guid,aacdb8ae-7baa-4423-a953-c18c1c7940ab.aspx"&gt;blog post&lt;/a&gt;.&amp;#160; Unfortunately, this implementation has one major problem: you cannot explicitly unregister.&amp;#160; In fact, the only way an attached listener no longer receives messages is if it gets garbage collected.&amp;#160; Our application happened to use this for an especially special event on our base entity: the infamous INotifyPropertyChanged event.&amp;#160; Needless to say, all the static WPF dependency objects left a whole bunch of leaked WeakReferences around (ironic?).&lt;/p&gt;  &lt;p&gt;But wait, doesn’t WPF already have a IWeakEventManager that solves this problem?&amp;#160; The problem with this is a couple things.&amp;#160; It’s slow.&amp;#160; It’s painful to use.&amp;#160; It’s annoying to implement.&amp;#160; Long story short, you need a static WeakEventManager for &lt;em&gt;every&lt;/em&gt; unique delegate.&amp;#160; Yes, sure, you can override a lot of the methods to make it more perform faster, but if you need to go that far you might as well write your own that does just what you need, and no more.&lt;/p&gt;  &lt;p&gt;If you haven’t found it already, Daniel Grunwald’s Code Project &lt;a href="http://www.codeproject.com/KB/cs/WeakEvents.aspx"&gt;article&lt;/a&gt; is yet another great resource.&amp;#160; My implementation was a mix of this and the earlier mentioned link.&amp;#160; Anywho, here it is:&lt;/p&gt;  &lt;pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;interface&lt;/span&gt; IWeakEventEntry&amp;lt;TSender, TArgs&amp;gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; IsAlive { &lt;span style="color: #0000ff"&gt;get&lt;/span&gt;; }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; Matches(Delegate handler);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; Invoke(SynchronizationPriority priority, TSender sender, TArgs args);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; WeakEventEntry&amp;lt;TTarget, TSource, TArgs&amp;gt; : IWeakEventEntry&amp;lt;TSource, TArgs&amp;gt; where TTarget : &lt;span style="color: #0000ff"&gt;class&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;delegate&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; OpenForwardingEventHandler(TTarget target, TSource sender, TArgs args);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; WeakReference m_TargetRef;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; OpenForwardingEventHandler m_OpenHandler;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; MethodInfo m_Method;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; WeakEventEntry(Delegate handler)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            m_OpenHandler = (OpenForwardingEventHandler)Delegate.CreateDelegate(&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(OpenForwardingEventHandler), &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;, handler.Method);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            m_TargetRef = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; WeakReference(handler.Target);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            m_Method = handler.Method;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; IsAlive { &lt;span style="color: #0000ff"&gt;get&lt;/span&gt; { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; m_TargetRef.IsAlive; } }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; Matches(Delegate handler)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; handler.Method == m_Method &amp;amp;&amp;amp; handler.Target == m_TargetRef.Target;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; Invoke(TSource sender, TArgs args)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            TTarget target = m_TargetRef.Target &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; TTarget;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (target != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                m_OpenHandler(target, sender, args);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; WeakEvent&amp;lt;TSender, TArgs&amp;gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; IWeakEventEntry&amp;lt;TSender, TArgs&amp;gt;[] EMPTY_LIST = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; IWeakEventEntry&amp;lt;TSender, TArgs&amp;gt;[0];
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; List&amp;lt;IWeakEventEntry&amp;lt;TSender, TArgs&amp;gt;&amp;gt; m_Events;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; IWeakEventEntry&amp;lt;TSender, TArgs&amp;gt;[] m_InvokeList = EMPTY_LIST;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; Count { &lt;span style="color: #0000ff"&gt;get&lt;/span&gt; { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; m_InvokeList.Length; } }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Add(Delegate handler)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (handler.Target == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) &lt;span style="color: #008000"&gt;// static method&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                Add(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; StrongEventEntry&amp;lt;TSender, TArgs&amp;gt;(handler));
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                Type type = &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(WeakEventEntry&amp;lt;,,&amp;gt;).MakeGenericType(handler.Target.GetType(), &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(TSender), &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(TArgs));
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                Add((IWeakEventEntry&amp;lt;TSender, TArgs&amp;gt;)type.GetConstructors()[0].Invoke(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt;[] { handler }));
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Add(IWeakEventEntry&amp;lt;TSender, TArgs&amp;gt; entry)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;lock&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (m_Events == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                    m_Events = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; List&amp;lt;IWeakEventEntry&amp;lt;TSender, TArgs&amp;gt;&amp;gt;(8);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                m_Events.Add(entry);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                m_InvokeList = m_Events.ToArray();
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Remove(Delegate handler)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;lock&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (m_Events != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; m_Events.Count; i++)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                    {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (m_Events[i].Matches(handler))
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                        {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                            m_Events.RemoveAt(i);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                            &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                        }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                    }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                    m_InvokeList = m_Events.ToArray();
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Clear()
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;lock&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                m_Events = &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                m_InvokeList = EMPTY_LIST;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Raise(TSender sender, TArgs args)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            IWeakEventEntry&amp;lt;TSender, TArgs&amp;gt;[] events = m_InvokeList;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; removeDead = &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = events.Length - 1; i &amp;gt;= 0; i--)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                removeDead |= !events[i].Invoke(sender, args);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (removeDead)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                RemoveDeadReferences();
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; RemoveDeadReferences()
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;lock&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (m_Events != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = m_Events.Count - 1; i &amp;gt;= 0; i--)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                    {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!m_Events[i].IsAlive)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                            m_Events.RemoveAt(i);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                    }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                    m_InvokeList = m_Events.ToArray();
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    }&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Nothing too special here.&amp;#160; For performance, a copy of all events are stored in an array so that raising events doesn’t need to be in a lock.&amp;#160; And while locking on “this” is usually bad practice, in this case I didn’t have any other local variable to use, and creating an object just for the sake of locking in my eyes was not worth it in this scenario.&lt;/p&gt;

&lt;p&gt;I tried generating the OpenForwardingDelegate using DynamicMethod and IL, but the result was negligible because it doesn’t actually affect invoking speed, which is what we’re most concerned with.&lt;/p&gt;

&lt;p&gt;Also, if you didn’t notice, this implementation also supports static methods attaching, hence why there is an IWeakEventEntry interface.&amp;#160; Here’s the StrongEventEntry implementation:&lt;/p&gt;

&lt;pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; StrongEventEntry&amp;lt;TSource, TArgs&amp;gt; : IWeakEventEntry&amp;lt;TSource, TArgs&amp;gt;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;delegate&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; ClosedForwardingEventHandler(TSource sender, TArgs args);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; ClosedForwardingEventHandler m_ClosedHandler;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; MethodInfo m_Method;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; IsAlive { &lt;span style="color: #0000ff"&gt;get&lt;/span&gt; { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;; } }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; StrongEventEntry(Delegate handler)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            m_Method = handler.Method;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            m_ClosedHandler = (ClosedForwardingEventHandler)Delegate.CreateDelegate(&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(ClosedForwardingEventHandler), &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;, handler.Method);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; Matches(Delegate handler)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; m_Method == handler.Method;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; Invoke(SynchronizationPriority priority, TSource sender, TArgs args)
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            m_ClosedHandler(sender, args);
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    }&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Last but not least, usage:&lt;/p&gt;

&lt;pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; WeakEvent&amp;lt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt;, PropertyChangedEventArgs&amp;gt; _propertyChanged = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; WeakEvent&amp;lt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt;, PropertyChangedEventArgs&amp;gt;();
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;event&lt;/span&gt; PropertyChangedEventHandler PropertyChanged
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        {
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            add { _propertyChanged.Add(&lt;span style="color: #0000ff"&gt;value&lt;/span&gt;); }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            remove { _propertyChanged.Remove(&lt;span style="color: #0000ff"&gt;value&lt;/span&gt;); }
&lt;/pre&gt;&lt;pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Performance is quite good.&amp;#160; On my machine for 1,000,000,000 invocations, it takes the WeakEvent ~17.3 seconds, vs 4.2 seconds for a standard delegate, for roughly 4x invocation cost.&lt;/p&gt;

&lt;p&gt;And there you have it!&amp;#160; A simple, generic, and fast weak event in ~200 lines of code.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-4113530620239179912?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/4113530620239179912/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=4113530620239179912' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/4113530620239179912'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/4113530620239179912'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2010/10/yet-another-weak-event-for-wpf.html' title='Yet Another Weak Event Implementation'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-8962364792275617363</id><published>2010-05-13T22:47:00.001-07:00</published><updated>2011-10-31T15:47:39.399-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IoC'/><category scheme='http://www.blogger.com/atom/ns#' term='Castle'/><title type='text'>Contextual Lifestyle with Castle Windsor</title><content type='html'>&lt;b&gt;EDIT:&lt;/b&gt;&amp;nbsp;As of version 3, scoped lifestyles are now a first class citizen supported out of the box (&lt;a href="http://docs.castleproject.org/Windsor.Whats-New-In-Windsor-3.ashx"&gt;http://docs.castleproject.org/Windsor.Whats-New-In-Windsor-3.ashx&lt;/a&gt;)&lt;br /&gt;
&lt;strong&gt;EDIT:&lt;/strong&gt; A much better implementation can be found at &lt;a href="https://github.com/castleprojectcontrib/Castle.Windsor.Lifestyles" title="https://github.com/castleprojectcontrib/Castle.Windsor.Lifestyles"&gt;https://github.com/castleprojectcontrib/Castle.Windsor.Lifestyles&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
IMO, one of the big missing features of Castle Windsor is that it doesn’t come with a built-in way for dealing with contextual lifestyles.&amp;nbsp; It handles transients and singletons fairly well, but once you get to other lifestyles it’s pretty heavily dependent on having some “state manager” handling the instances.&amp;nbsp; For example, PerWebRequest uses the HttpContext, PerThread uses thread static variables, etc.&lt;br /&gt;
Contextual lifestyles is one of those things where it doesn’t seem all that useful at first, and then when you see the possibilities it’s like getting hit with a huge truck.&lt;br /&gt;
A question was posted to the Castle Google Group recently, which I follow, which illustrates a relatively common example of why someone would want to have a contextual lifestyle.&amp;nbsp; Basically, you have a whole bunch of components you want to resolve, but only within a context.&lt;br /&gt;
Here’s some boiler plate code of the domain model:&lt;br /&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IRepository { ISession Session { get; } }
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; ISession : IDisposable { &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsDisposed { get; } }
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Session : ISession
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsDisposed { get; set; }
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Dispose() { IsDisposed = &lt;span class="kwrd"&gt;true&lt;/span&gt;; }
}
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Repository1 :IRepository
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; ISession Session { get; &lt;span class="kwrd"&gt;private&lt;/span&gt; set; }
    &lt;span class="kwrd"&gt;public&lt;/span&gt; Repository1(ISession session){ Session = session; }
}
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Repository2 : IRepository
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; ISession Session { get; &lt;span class="kwrd"&gt;private&lt;/span&gt; set; }
    &lt;span class="kwrd"&gt;public&lt;/span&gt; Repository2(ISession session){ Session = session; }
}
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Model1
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; IRepository First { get; &lt;span class="kwrd"&gt;private&lt;/span&gt; set; }
    &lt;span class="kwrd"&gt;public&lt;/span&gt; IRepository Second { get; &lt;span class="kwrd"&gt;private&lt;/span&gt; set; }
    &lt;span class="kwrd"&gt;public&lt;/span&gt; Model1(IRepository first, IRepository second) { First = first; Second = second; }
}
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Model2
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; IRepository Second { get; &lt;span class="kwrd"&gt;private&lt;/span&gt; set; }
    &lt;span class="kwrd"&gt;public&lt;/span&gt; Model2(IRepository second) { Second = second; }
}&lt;/pre&gt;&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
 font-size: small;
 color: black;
 font-family: consolas, "Courier New", courier, monospace;
 background-color: #ffffff;
 /*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
 background-color: #f4f4f4;
 width: 100%;
 margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;And here’s the unit test I want to pass:&lt;br /&gt;
&lt;pre class="csharpcode"&gt;[Test]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ResolutionsByContext()
        {
            IWindsorContainer root = &lt;span class="kwrd"&gt;new&lt;/span&gt; WindsorContainer();
            root.Register(Component.For&amp;lt;Model1&amp;gt;().LifeStyle.Transient,
                          Component.For&amp;lt;Model2&amp;gt;().LifeStyle.Transient,
                          Component.For&amp;lt;IRepository&amp;gt;().ImplementedBy&amp;lt;Repository1&amp;gt;().LifeStyle.Transient,
                          Component.For&amp;lt;IRepository&amp;gt;().ImplementedBy&amp;lt;Repository2&amp;gt;().LifeStyle.Transient,
                          Component.For&amp;lt;ISession&amp;gt;().ImplementedBy&amp;lt;Session&amp;gt;().LifeStyle.PerContextScope());

            Model1 model1;
            Model2 model2;
            ISession session1, session2;
            &lt;span class="kwrd"&gt;using&lt;/span&gt; (var context1 = root.BeginLifetimeScope())
            {
                model1 = context1.Resolve&amp;lt;Model1&amp;gt;();
                session1 = model1.First.Session;
                Assert.AreSame(model1.First.Session, model1.Second.Session);
                Assert.AreSame(context1.Resolve&amp;lt;ISession&amp;gt;(), context1.Resolve&amp;lt;ISession&amp;gt;());

                &lt;span class="kwrd"&gt;using&lt;/span&gt; (var context2 = root.BeginLifetimeScope())
                {
                    model2 = context2.Resolve&amp;lt;Model2&amp;gt;();
                    session2 = model2.Second.Session;
                    Assert.AreNotSame(model1.First.Session, model2.Second.Session);

                    var anotherModel2 = context2.Resolve&amp;lt;Model2&amp;gt;();
                    Assert.AreSame(anotherModel2.Second.Session, model2.Second.Session);

                    Assert.AreSame(session2, context2.Resolve&amp;lt;ISession&amp;gt;());
                    Assert.AreNotSame(context1.Resolve&amp;lt;ISession&amp;gt;(), context2.Resolve&amp;lt;ISession&amp;gt;());
                }
                Assert.IsTrue(session2.IsDisposed);
                Assert.IsFalse(session1.IsDisposed);
            }
            Assert.IsTrue(session1.IsDisposed);
        }&lt;/pre&gt;&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
 font-size: small;
 color: black;
 font-family: consolas, "Courier New", courier, monospace;
 background-color: #ffffff;
 /*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
 background-color: #f4f4f4;
 width: 100%;
 margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;  &lt;br /&gt;
I copied the name BeginLifetimeScope from Autofac, which inherently supports contextual scopes as a first-class citizen (of which the test passes).&amp;nbsp; The question now, is how do we get Castle Windsor to do the same?&lt;br /&gt;
Initially, I took a look at ISubDependencyResolver and caching variables.&amp;nbsp; Unfortunately, this didn’t work too well because sub resolvers never got hit if they were resolved from the container directly.&lt;br /&gt;
The next step I tried was with lifestyle managers, but alas, the CreationContext was always transient and I was unable to store any state that distinguished between different context resolutions.&lt;br /&gt;
After digging deeper into the Windsor codebase and getting into the subsystems and handlers, I found a solution that seems to work.&amp;nbsp; It passes the test above, but that’s about it.&amp;nbsp; Test well if you’re gonna use this in production code!!!&lt;br /&gt;
Here goes!&lt;br /&gt;
First, you have a lifestyle manager to distinguish between other lifestyles.&lt;br /&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ContextualLifestyleManager : AbstractLifestyleManager
    {
        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt; instance;
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt; Resolve(CreationContext context)
        {
            &lt;span class="kwrd"&gt;return&lt;/span&gt; instance ?? (instance = &lt;span class="kwrd"&gt;base&lt;/span&gt;.Resolve(context));
        }
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Dispose()
        {
        }
    }&lt;/pre&gt;And finally, the magic happens with this:&lt;br /&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ContextualExtensions
    {
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; ComponentRegistration&amp;lt;T&amp;gt; PerContextScope&amp;lt;T&amp;gt;(&lt;span class="kwrd"&gt;this&lt;/span&gt; LifestyleGroup&amp;lt;T&amp;gt; group)
        {
            &lt;span class="kwrd"&gt;return&lt;/span&gt; group.Custom&amp;lt;ContextualLifestyleManager&amp;gt;();
        }
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; IWindsorContainer BeginLifetimeScope(&lt;span class="kwrd"&gt;this&lt;/span&gt; IWindsorContainer parent)
        {
            var child = &lt;span class="kwrd"&gt;new&lt;/span&gt; WindsorContainer();
            var ss = (INamingSubSystem)parent.Kernel.GetSubSystem(SubSystemConstants.NamingKey);
            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var handler &lt;span class="kwrd"&gt;in&lt;/span&gt; ss.GetHandlers())
            {
                &lt;span class="kwrd"&gt;if&lt;/span&gt; (handler.ComponentModel.CustomLifestyle == &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(ContextualLifestyleManager))
                {
                    child.Kernel.AddCustomComponent(handler.ComponentModel);
                }
            }
            parent.AddChildContainer(child);
            &lt;span class="kwrd"&gt;return&lt;/span&gt; child;
        }
    }&lt;/pre&gt;First method is just a helper method to be a little more fluent in the registration for when you want many things to have contextual lifestyle.&amp;nbsp; The second method is the guts.&amp;nbsp; Long story short, we create a child container, and duplicate all component models of contextual lifestyle.&amp;nbsp; Thus, whenever components are resolved, the “override” is found in the child and resolved.&amp;nbsp; Anything else will be found in the parent.&lt;br /&gt;
I was initially pretty happy with this, until I profiled the performance.&amp;nbsp; With Autofac, creating and disposing 100,000 contexts took 5ms on my computer.&amp;nbsp; Doing the same with with Windsor took 3.8 &lt;strong&gt;seconds&lt;/strong&gt;.&amp;nbsp; Out of curiosity, I profiled again, but this time just creating child containers without copying handlers down: 1.9 seconds.&amp;nbsp; So while this implementation works, it’s not as performant as I’d like it to be….&lt;br /&gt;
Maybe I’ll come up with another solution, but for now if the performance is acceptable maybe this would be useful for others!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-8962364792275617363?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/8962364792275617363/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=8962364792275617363' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/8962364792275617363'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/8962364792275617363'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2010/05/contextual-lifestyle-with-castle.html' title='Contextual Lifestyle with Castle Windsor'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-4655364093999212282</id><published>2010-04-21T17:31:00.000-07:00</published><updated>2011-10-31T15:47:46.147-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IoC'/><category scheme='http://www.blogger.com/atom/ns#' term='Castle'/><title type='text'>Forcing Castle Windsor to Generate Class Proxies</title><content type='html'>I don't know why it took me so long to come up with this idea, but to save others potential headaches...have you ever thought "hmmmm, I registered this as an interface with an implementation, but I want Windsor to use a class proxy, not an interface proxy, how do I do that?"&lt;br /&gt;
&lt;br /&gt;
For me, initially I &lt;i&gt;almost&lt;/i&gt; went as far as implementing my own ProxyFactory to force it to use class proxy no matter what, and then the light bulb hit me and it turns out that there's a much easier way to accomplish this.&lt;br /&gt;
&lt;br /&gt;
c.Register(Component.For&amp;lt;ConcreteImpl, IService&amp;gt;().Interceptors&amp;lt;AnInterceptor&amp;gt;());&lt;br /&gt;
&lt;br /&gt;
Tada!&amp;nbsp; The actual service is now a concrete type, so Windsor will go, OK, I need to create a class proxy.&amp;nbsp; But since it's forwarded to the interface as well, all your dependencies can simply use the interface and everything magically works.&lt;br /&gt;
&lt;br /&gt;
Yay!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-4655364093999212282?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/4655364093999212282/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=4655364093999212282' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/4655364093999212282'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/4655364093999212282'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2010/04/forcing-castle-windsor-to-generate.html' title='Forcing Castle Windsor to Generate Class Proxies'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-7528377316246787299</id><published>2010-04-05T19:43:00.000-07:00</published><updated>2010-12-05T17:52:04.538-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><title type='text'>How to Advocate Test Driven Development (TDD)</title><content type='html'>It seems that everywhere you read you will find blog posts asserting that it is difficult to convince others to use TDD, and that everyone talking about TDD is already a believer preaching to other believers.&amp;nbsp; So what's the best way convince others?&lt;br /&gt;
&lt;br /&gt;
I recently convinced a good buddy of me to starting doing TDD in his web development.&amp;nbsp; It took a while, but finally he "saw the light."&amp;nbsp; He tried to relay the information to his coworker, and his coworker didn't react as positively, citing the common "I don't want to waste time writing test code when I know my stuff works."&lt;br /&gt;
&lt;br /&gt;
There are many many &lt;b&gt;MANY&lt;/b&gt; hurdles of overcome to begin writing software using TDD.&amp;nbsp; I won't go into great detail since you can easily find relevant posts on the web, but basically, if you &lt;i&gt;have&lt;/i&gt; successfully transitioned to TDD that also implies that you have in one way or another adopted&amp;nbsp;&lt;a href="http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod"&gt;S.O.L.I.D. principles&lt;/a&gt; in software design.&lt;br /&gt;
&lt;br /&gt;
The reason I say this is because it is literally impossible to do TDD otherwise.&amp;nbsp; It is just plain &lt;b&gt;painful&lt;/b&gt;.&amp;nbsp; I've been there.&amp;nbsp; It is so painful you shout in your head WTF are people thinking, how does this make my job easier?!&lt;br /&gt;
&lt;br /&gt;
Usually when this happens, you'll probably notice that most (or all) of the SOLID principles have been violated one way or another.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sarcasm&amp;gt;&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Single Responsibility Principle&lt;/li&gt;

&lt;ul&gt;&lt;li&gt;You mean 1 class to rule them all right?&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Open Closed Principle&lt;/li&gt;

&lt;ul&gt;&lt;li&gt;Does this have something to do with sockets?&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Liskov Substitution Principle&lt;/li&gt;

&lt;ul&gt;&lt;li&gt;I thought the point of Object Oriented Programming is that &lt;i&gt;everything&lt;/i&gt; is an object!&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Interface Segregation Principle&lt;/li&gt;

&lt;ul&gt;&lt;li&gt;What's an interface?&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Dependency Inversion Principle&lt;/li&gt;

&lt;ul&gt;&lt;li&gt;I don't get it...I only have 1 super object anyway, I don't have dependencies.&lt;/li&gt;
&lt;/ul&gt;&lt;/ul&gt;&amp;lt;/sarcasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notice that even though this post was supposed to be about how to advocate TDD, I ended up talking about SOLID instead for a bit.&amp;nbsp; What am I trying to get at?&lt;br /&gt;
&lt;br /&gt;
TDD spans from the individual to the team to the organization.&amp;nbsp; You need to be able to tackle it from all points of view.&amp;nbsp; The obsession of the word 'test' has hurt TDD quite a bit.&amp;nbsp; Anyone who's spent any reasonable amount of time will assert that tests are just a means to drive the design.&amp;nbsp; Tests should read like a story (well to programmer eyes), and yes, I said read, as in &lt;i&gt;readable!&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
At the individual level, you must convince them it forces you to design better code, because testing against badly designed code is not worth the pain/annoyance.&amp;nbsp; You must assert that better designed code is good because it also means being more maintainable and less bugs.&lt;br /&gt;
&lt;br /&gt;
At the team level, you must convince that collective code ownership is a good thing.&amp;nbsp; There should never be a situation where "Bob's on vacation, we'll need to put a hold on Project A because only he knows it".&amp;nbsp; Tests serve as a way on how to interact with a specific service, and are a jump-start to figuring out how to actually &lt;b&gt;use&lt;/b&gt; a particular service.&amp;nbsp; Moreover, collective code ownership is a means of sharing and distributing knowledge.&lt;br /&gt;
&lt;br /&gt;
At the organizational level, you must convince managers that you are a professional software developer, and that it is your job to produce high quality work.&amp;nbsp; And if what is required to produce high quality work involves writing proper unit tests, following SOLID principles, and even other agile practices like pair programming, then you should be allowed (and optimally encouraged) to do so.&amp;nbsp; Now TDD might not work for everyone, or every organization, but I think everyone owes it to themselves to give it a fair chance.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3157881265969801285-7528377316246787299?l=blingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blingcode.blogspot.com/feeds/7528377316246787299/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3157881265969801285&amp;postID=7528377316246787299' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/7528377316246787299'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3157881265969801285/posts/default/7528377316246787299'/><link rel='alternate' type='text/html' href='http://blingcode.blogspot.com/2010/04/how-to-advocate-test-driven-development.html' title='How to Advocate Test Driven Development (TDD)'/><author><name>bling</name><uri>http://www.blogger.com/profile/12728014380144489730</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3157881265969801285.post-6497133217930972231</id><published>2010-04-05T19:16:00.001-07:00</published><updated>2011-10-31T15:47:59.965-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IoC'/><category scheme='http://www.blogger.com/atom/ns#' term='Castle'/><title type='text'>Windsor/DynamicProxy/Mixin Powers!</title><content type='html'>Hmmm, I couldn’t really think of a good title except that this blog post has a little bit of everything of the title.&lt;br /&gt;
&lt;br /&gt;
As with any multithreaded program, deadlocks are a huge pain in the butt, and when they happen it costs time, money, and stress.&lt;br /&gt;
&lt;br /&gt;
In my code base I’ve introduced something called an ExtendedLock, which basically has something like this inside:&lt;br /&gt;
&lt;div class="csharpcode"&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ExtendedLock : IExtendedLock {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;  &lt;span class="kwrd"&gt;public&lt;/span&gt; IDisposable Lock() {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    &lt;span class="kwrd"&gt;while&lt;/span&gt; (!Monitor.TryEnter(&lt;span class="kwrd"&gt;this&lt;/span&gt;, 5000)) {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;      IncrementLockTime();&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; Disposer(() =&amp;gt; Release());&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;  }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   8:    public event Deadlock;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;9&lt;span class="lnum"&gt;: &lt;/span&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;&lt;br /&gt;
&lt;br /&gt;
Pretty simple.&amp;nbsp; IncrementLockTime, as the name implies keeps track of how long the current thread has been attempting to acquire the lock.&amp;nbsp; It returns a Disposer which takes an Action, which releases the lock.&amp;nbsp; This allows us to take advantage of the &lt;b&gt;using&lt;/b&gt; syntax, and avoid boiler plate try/finally (oh, and it avoids typos in Monitor.Exit).&amp;nbsp; After some configurable amount of time, if the lock cannot be acquired within, say, 2 minutes, it’s probably a good probability your application is blocked somewhere.&lt;br /&gt;
&lt;br /&gt;
Now, using this class basically means replacing lock(_syncRoot) type code with _elock.Lock().&amp;nbsp; Also, I believe it’s a good candidate for “mixing” into any other component.&amp;nbsp; Mixins are sort of like multiple-inheritance, but not.&amp;nbsp; I like to think of mixins as a “can do” rather than “is a.”&lt;br /&gt;
&lt;br /&gt;
Now, we know that C# doesn’t let you do multiple inheritance, but with libraries like Castle’s DynamicProxy2, it lets you do something very similar, and is extremely powerful.&amp;nbsp; In a sense, it will automatically generate the following code for you:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="csharpcode"&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; SomeService : ISomeService, IExtendedLock {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;  IExtendedLock _lock = &lt;span class="kwrd"&gt;new&lt;/span&gt; ExtendedLock();&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;  &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; DoSomething() { }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;  IDisposable IExtendedLock.Lock() { &lt;span class="kwrd"&gt;return&lt;/span&gt; _lock.Lock(); }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;/div&gt;&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;&lt;br /&gt;
&lt;br /&gt;
_lock is a private instance variable, SomeService implements IExtendedLock, and simply redirects all the interface methods to _lock.&amp;nbsp; This seems pretty simple and straightforward, but becomes tedious when the type you want to mix in has many methods (as my actual IExtendedLock is).&lt;br /&gt;
&lt;br /&gt;
With Windsor/DynamicProxy, you can do this automatically with minimal amount of code.&amp;nbsp; For example, first you define something like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; ILockableDictionary : IDictionary, IExtendedLock { }&lt;/pre&gt;&lt;br /&gt;
Then, you register it in the container:&lt;br /&gt;
&lt;div class="csharpcode"&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;var container = &lt;span class="kwrd"&gt;new&lt;/span&gt; WindsorContainer();&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;container.Register(Component.For(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(ILockableHashtable))&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;                                   .LifeStyle.Transient&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;                                   .Activator&amp;lt;LockableHashtableActivator&amp;gt;());&lt;/pre&gt;&lt;/div&gt;&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;&lt;br /&gt;
&lt;br /&gt;
Now, whenever you need an instance of a lockable hashtable you can simply do something like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="csharpcode"&gt;var hash = container.Resolve&amp;lt;ILockableHashtable&amp;gt;();
&lt;span class="kwrd"&gt;using&lt;/span&gt; (hash.Lock()) {
hash[&lt;span class="str"&gt;"1"&lt;/span&gt;] = 1;
}&lt;/pre&gt;&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;&lt;br /&gt;
&lt;br /&gt;
You might be wondering why it’s worth all this trouble, and what’s wrong with regular locks and Monitor.&amp;nbsp; For our system it’s pretty critical that it stays running 24/7, and every minute it’s down is money lost, so it is in our best interest to detect any problematic condition.&lt;br /&gt;
&lt;br /&gt;
Last but not least, here’s the important code that actually generates the proxy:&lt;br /&gt;
&lt;div class="csharpcode"&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; LockableHashtableActivator : DefaultComponentActivator&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;{&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; LockableHashtableActivator(ComponentModel model, IKernel kernel, ComponentInstanceDelegate onCreation, ComponentInstanceDelegate onDestruction)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;        : &lt;span class="kwrd"&gt;base&lt;/span&gt;(model, kernel, onCreation, onDestruction)&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt; Create(CreationContext context)&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;    {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;        IExtendedLock lockMixin = Kernel.Resolve&amp;lt;IExtendedLock&amp;gt;();&lt;/pre&g
