<?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-15527242</id><updated>2011-07-28T07:37:24.824-07:00</updated><category term='musings'/><title type='text'>::swingsetacid::</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Joshua Ewer</name><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>24</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-15527242.post-7965439495097478515</id><published>2010-03-31T12:40:00.000-07:00</published><updated>2010-03-31T12:55:32.532-07:00</updated><title type='text'>The Time-Honoured Rules of Foursquare</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_-aAqftrAWm4/S7OmieyR0yI/AAAAAAAAAdw/Z-vYtUFy3E0/s1600/EDWARDIANGENTLEMANWITHBALL.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 230px; height: 320px;" src="http://4.bp.blogspot.com/_-aAqftrAWm4/S7OmieyR0yI/AAAAAAAAAdw/Z-vYtUFy3E0/s320/EDWARDIANGENTLEMANWITHBALL.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5454886684985512738" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span"  style="color:#0000EE;"&gt;&lt;u&gt;&lt;br /&gt;&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;While you may find variations on Foursquare rules in many places, the specific rules of this game are as follows:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;The Playing Surface&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;2 144 ft^2 squares divided into quadrants&lt;/li&gt;&lt;li&gt;Three squares will be labeled with a royalty mark (Ace, King, Queen); the fourth will be left blank.  The blank square will contain a hashed box called the "service square" where serves must be delivered.&lt;/li&gt;&lt;li&gt;Outside lines are in, inside lines are out. Players waiting in line are considered out-of-bounds. Inanimate objects or passersby are considered in-bounds and are playable, assuming said objects do not actively attempt to redirect the ball.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_-aAqftrAWm4/S7OmtR4uUyI/AAAAAAAAAd4/kCtUFGtobVg/s1600/foursquare.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px; height: 255px;" src="http://1.bp.blogspot.com/_-aAqftrAWm4/S7OmtR4uUyI/AAAAAAAAAd4/kCtUFGtobVg/s320/foursquare.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5454886870501446434" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;The Rules of the Game&lt;/b&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;The Player in the Ace square is responsible for serving. &lt;/li&gt;&lt;li&gt;There is "no blood on a serve" meaning the serve *must be returnable* by being 1) served to the player in the unmarked square, 2) bouncing once inside the service square (see wall photo). &lt;/li&gt;&lt;li&gt;Server gets one fault (i.e. the ball does not bounce inside service square) per round and may re-serve after the first fault is called.   The fault &lt;i&gt;must be called by the Player being served&lt;/i&gt; or the serve will be considered legal.  Two called faults result in the Server being ejected from the Ace square.&lt;/li&gt;&lt;li&gt;A Player is out if the ball touches them last before landing on an inside line or outside the outer boundaries.  The remaining Players then advance upwards in royalty.&lt;/li&gt;&lt;li&gt;The ball may be hit in any fashion with any part of the body.  There will be no enforcement of the time-honored "Underhand Only" or "No Feets" rules.  However, a hit &lt;i&gt;must cause a perceptable change in direction or velocity&lt;/i&gt;.&lt;/li&gt;&lt;li&gt;Rolling the ball across the line shall be considered an illegal hit.&lt;/li&gt;&lt;li&gt;As this is a gentle(wo)man's game, it will be self-refereed under the honor system. If two Players cannot agree on a game decision, then the "Two (Wo)Men Enter, One (Wo)Man Leaves" rule comes into play. In this scenario, a two-square battle will be played, with the losing Player being ejected from their square.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;b&gt;Advanced Moves&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;If a ball bounces in a Player's square, the ball must be hit by that square's Player. Another Player may not steal the ball. However, a Player may reach across and steal the ball before the ball bounces. Such a move shall be called "The Snake."&lt;/li&gt;&lt;li&gt;If a ball is hit up into the air, a Player may stop the ball's trajectory and redirect it back into the square, but it must bounce once in the Player's square before being hit out. Such a move shall be called "A Bus Stop."&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;The tournament structure is as follows:&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;A Player receives &lt;b&gt;one &lt;/b&gt;point for each round survived in the King and Queen squares.  A Player receives &lt;b&gt;two &lt;/b&gt;points for each round survived in the Ace square as the Server.&lt;/li&gt;&lt;li&gt;The first half of the Players that reach an arbitrarily decided number of points (100?) will be entered into the competitor's bracket for the prize.  The remaining half will be continue to play for the lower bracket's prize.&lt;/li&gt;&lt;li&gt;The bracket competitions will be &lt;b&gt;Five&lt;/b&gt;-elimination.  You continue to remain in the game until you have been eliminated 5 times.  The game continues until 4 players remain.  When four players remain, all eliminations are reset and the Final Round commences.&lt;/li&gt;&lt;li&gt;In the final round, all players receive one point for surviving a round.  The first player to reach 10 points is summarily declared the Winner of that bracket and receives the bracket's Prize.&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15527242-7965439495097478515?l=swingsetacid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/7965439495097478515/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15527242&amp;postID=7965439495097478515' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/7965439495097478515'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/7965439495097478515'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/2010/03/time-honoured-rules-of-foursquare.html' title='The Time-Honoured Rules of Foursquare'/><author><name>Joshua Ewer</name><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://4.bp.blogspot.com/_-aAqftrAWm4/S7OmieyR0yI/AAAAAAAAAdw/Z-vYtUFy3E0/s72-c/EDWARDIANGENTLEMANWITHBALL.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15527242.post-5044143493031370536</id><published>2009-08-21T13:45:00.000-07:00</published><updated>2009-08-21T14:23:23.286-07:00</updated><title type='text'>Granularity in Kanban</title><content type='html'>Kanban is pretty freeform, I'll admit.  Coming from Scrum, which is pretty free-wheeling in itself, I feel like there's very little I'm "required" to do.  I can kind of make it up as I go.  While I think that's intrinsic to the adaptive nature of lean, and kanban in particular, it does feel a little like I'm out on my own.&lt;br /&gt;&lt;br /&gt;One thing that's painfully obvious: the ready, in progress, and complete states are not granular enough.&lt;br /&gt;&lt;br /&gt;I know, I know.  That's obvious.&lt;br /&gt;&lt;br /&gt;Still, I find myself adding a state in the workflow every day or so.  Fortunately, it's incredibly easy to tweak the workflow w/o disrupting forward progress.  After a week, here's where I'm at.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_-aAqftrAWm4/So8Lxd9opsI/AAAAAAAAAA0/mkcrwa2nZHc/s1600-h/photo.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 320px; height: 240px;" src="http://3.bp.blogspot.com/_-aAqftrAWm4/So8Lxd9opsI/AAAAAAAAAA0/mkcrwa2nZHc/s320/photo.jpg" alt="" id="BLOGGER_PHOTO_ID_5372525824960931522" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;As you can tell, granularity organically grew as I got more comfortable w/ the process.  There are different WIP limits in each section of "in progress."  My particular need is different, since I'm using my transition to a new gig as my backlog, but in software development you still have the "i'm doing R&amp;amp;D, i'm working on unit tests, i'm waiting on infrastructure" types of states.  You'll have an incredibly amount of flexibility in determining how you should gate or throttle your work in progress, but it will take time for a team to figure out exactly how they should tweak their limits.&lt;br /&gt;&lt;br /&gt;All in all, I'm really excited to apply this methodology to an actual software project....&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15527242-5044143493031370536?l=swingsetacid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/5044143493031370536/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15527242&amp;postID=5044143493031370536' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/5044143493031370536'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/5044143493031370536'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/2009/08/granularity-in-kanban.html' title='Granularity in Kanban'/><author><name>Joshua Ewer</name><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://3.bp.blogspot.com/_-aAqftrAWm4/So8Lxd9opsI/AAAAAAAAAA0/mkcrwa2nZHc/s72-c/photo.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15527242.post-6492831411207981803</id><published>2009-08-12T15:57:00.001-07:00</published><updated>2009-08-13T08:54:34.966-07:00</updated><title type='text'>New beginnings, new methodologies</title><content type='html'>So, I doubt more than a handful of people read this (I do this for my own cathartic purposes, really) and everyone that does knows that I've taken a new position starting in September.  These same people also know I might be a bit of an Agile fanatic.  Scrum (which, honestly, is still my fav methodology) has lost a bit of its well-earned sheen, Lean and, specifically, Kanban have become the new silver bullet.&lt;br /&gt;&lt;br /&gt;So, being the sucker for shiny new toys, I need to try it out.  So, I've decomposed all the items I need to transition into work items on a kanban board.  While I won't have time here (I leave Sept. 4th) to see the fruits of it in a development sense, I do get a good sense of how to track work with it.  I've been doing &lt;a href="http://leansoftwareengineering.com/ksse/scrum-ban/"&gt;Scrum-ban&lt;/a&gt; for quite some time now so the pull concept of Kanban makes sense.  There are so many interesting variations of how to limit work in progress and model workflow that I'm actually excited to try it.&lt;br /&gt;&lt;br /&gt;More notes later...&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://s3.amazonaws.com/twitpic/photos/large/22950390.jpg?AWSAccessKeyId=0ZRYP5X5F6FSMBCCSE82&amp;amp;Expires=1250121736&amp;amp;Signature=O2s2HqOZaLKHqpoXEb9nbYaikxE%3D"&gt;&lt;/a&gt;&lt;a href="https://twitpic.com/dnwmu"&gt;(a pic of my kanban board is here)&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15527242-6492831411207981803?l=swingsetacid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/6492831411207981803/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15527242&amp;postID=6492831411207981803' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/6492831411207981803'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/6492831411207981803'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/2009/08/new-beginnings-new-methodologies.html' title='New beginnings, new methodologies'/><author><name>Joshua Ewer</name><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-15527242.post-3645902636239363995</id><published>2009-05-19T10:56:00.000-07:00</published><updated>2009-05-19T11:11:18.276-07:00</updated><title type='text'>TFS - Don't allow "Resolved" on checkins</title><content type='html'>This is the third or fourth time I've done this, so I thought I should put it here for the fifth or sixth time ;-)  I have yet to find this away without getting dirty in the Xml (doing this in the GUI doesn't seem to work).&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;In VS 2008, export the work item type (probably task, if you're using Agile 4.0) to an Xml file (if it asks you to include any Global Lists, just say no).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Open w/ yr Xml editor (I use Notepad++)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Find the TRANSITION node between the two states you care about.  (Xpath would look much like "//WORKFLOW/TRANSITIONS[TRANSITION[@from='Active' and @to='Closed']])&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Under this node, you'll find an ACTIONS/ACTION node containing a value like "Microsoft.VSTS.Actions.Checkin".&lt;/li&gt;&lt;li&gt;Delete that entire "ACTIONS" node.&lt;/li&gt;&lt;li&gt;Save the file.&lt;/li&gt;&lt;li&gt;Import the work item definition back into TFS, effectively overwriting the existing definition.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Profit!&lt;/li&gt;&lt;/ol&gt;Note:  As always, I googled to see if someone had figured out the GUI angle.  Lo and behold, Martin Woodward has blogged about this before, bless his heart.  Due credit goes here:&lt;br /&gt;&lt;br /&gt;http://www.woodwardweb.com/vsts/000230.html&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15527242-3645902636239363995?l=swingsetacid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/3645902636239363995/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15527242&amp;postID=3645902636239363995' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/3645902636239363995'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/3645902636239363995'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/2009/05/tfs-dont-allow-resolved-on-checkins.html' title='TFS - Don&apos;t allow &quot;Resolved&quot; on checkins'/><author><name>Joshua Ewer</name><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-15527242.post-3460628271833206227</id><published>2009-05-12T14:27:00.000-07:00</published><updated>2009-05-12T15:27:00.371-07:00</updated><title type='text'>Team Build and NUnit - Together At Last!</title><content type='html'>Perhaps this is already well-known, but I've scoured a bunch of sites trying to find a simple, yet comprehensive plan for getting NUnit tests to run as part of a Team Build script. I had to explain this to someone earlier this week, and I would have loved to just point them to a simple doc. So, next time, I'll point them here:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;ItemGroup&gt;&lt;br /&gt;&lt;br /&gt;&lt;TestAssembly Include="E:\NUnitTests\HelloWorld_NUnitTest.dll" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/ItemGroup&gt;&lt;br /&gt;&lt;br /&gt;&lt;Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;Target Name="PostBuild"&gt;&lt;br /&gt;&lt;br /&gt;&lt;NUnit Assemblies="@(TestAssembly)" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/Target&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15527242-3460628271833206227?l=swingsetacid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/3460628271833206227/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15527242&amp;postID=3460628271833206227' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/3460628271833206227'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/3460628271833206227'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/2009/05/team-build-and-nunit-together-at-last.html' title='Team Build and NUnit - Together At Last!'/><author><name>Joshua Ewer</name><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-15527242.post-2168967706226827153</id><published>2009-03-31T12:08:00.001-07:00</published><updated>2009-03-31T12:27:44.124-07:00</updated><title type='text'>AOP in .NET</title><content type='html'>So, despite promising a treatise on REST in WCF/.NET, I realize that others have said it far better than I (e.g.):&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/RESTful-NET-Build-Consume-Services/dp/0596519206"&gt;Jon Flanders&lt;/a&gt;&lt;br /&gt;&lt;a href="http://tomayko.com/writings/rest-to-my-wife"&gt;Ryan Tomayko&lt;/a&gt; (i liked this a lot, despite the stupid complaints of sexism. sheesh.)&lt;br /&gt;and, oh, this company called &lt;a href="http://www.asp.net/downloads/starter-kits/wcf-rest/"&gt;Microsoft&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;So, on to another pet project: &lt;a href="http://en.wikipedia.org/wiki/Aspect-oriented_programming"&gt;aspect-oriented programming&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I've been obsessed with writing really lean, tight code as of late. In looking back on some of my work in the last couple years, having a new perspective of (the lack of) ROI on some premature optomization, I can pick out dozens of places where I would have thought (then) "oh, &lt;strong&gt;&lt;em&gt;some day&lt;/em&gt;&lt;/strong&gt; someone will need this" whereas I'd say now "is anyone &lt;strong&gt;&lt;em&gt;honestly&lt;/em&gt;&lt;/strong&gt; going to use this?" Of course, following TDD as a methodology helps me there too ;-)&lt;br /&gt;&lt;br /&gt;So, I want to log exceptions. I also, for debug purposes, might want to log, well, everything.&lt;br /&gt;&lt;br /&gt;I have it narrowed down to two options: runtime weaving with &lt;a href="http://www.springframework.net/"&gt;Spring.NET &lt;/a&gt;and compile-time weaving with &lt;a href="http://www.postsharp.org/"&gt;PostSharp&lt;/a&gt;. The terms are self-explanatory (unlike other AOP jargon).  While I think either could be used in either case, they have clear strengths in their respective foci (or, focuses).&lt;br /&gt;&lt;br /&gt;Spring.Net.  It's all runtime, meaning it's .NET language agnostic, and it all plays very, very nicely with Spring's IoC containers.  I noted it doesn't allow you to do field interception (cool idea, but the power is too ripe for abuse and leads to bad OO design), just method interception, but that lets you cover everything you honestly need to do . . . Still I hate it when I know I can't do something, even though I have no business needing to do it.&lt;br /&gt;&lt;br /&gt;PostSharp, as I mentioned, does do runtime weaving, but it really does an amazing job with compile-time weaving.  If you've dealt with this technique, your big objection is noted.  Yes, it's dificult to debug and, yes, it is magic.  I know, it scares me too.  But, when, (as in the case of &lt;a href="http://code.google.com/p/postsharp-user-plugins/wiki/Log4PostSharp"&gt;log4PostSharp&lt;/a&gt;) I can literally have system-wide logging with ONE line of code in AssemblyInfo, I'm hooked.  It's a fair trade.&lt;br /&gt;&lt;br /&gt;I'll see how it goes.  Though, I've built fairly robust logging into three separate service stacks in the course of a few hours using PostSharp. &lt;br /&gt;&lt;br /&gt;I think I'm hooked.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15527242-2168967706226827153?l=swingsetacid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/2168967706226827153/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15527242&amp;postID=2168967706226827153' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/2168967706226827153'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/2168967706226827153'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/2009/03/aop-in-net.html' title='AOP in .NET'/><author><name>Joshua Ewer</name><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-15527242.post-7241290794616628868</id><published>2009-02-26T09:48:00.000-08:00</published><updated>2009-02-26T09:59:18.706-08:00</updated><title type='text'>WCF will do the REST of it for you...</title><content type='html'>So, in the interests of interop, we're going to be exposing all of our SOAP/WS-* services RESTfully too. Okay, I'm there conceptually, but I have some serious concerns about logistics.&lt;br /&gt;&lt;br /&gt;So, I thought I'd detail what it takes to go from a "Microsoftie-thats-perfectly-happy-with-SOAP-because-Visual-Studio-does-all-the-hard-work-for-me" type to a "hey-lookee-lookee-I'm-interoperable-because-I've-been-freed-from-the-strictures-of-WS-*" type.&lt;br /&gt;&lt;br /&gt;Note that this is, for some reason, a highly charged topic to discuss.  While I'm sure I have enough say that I could put the kibosh on the whole thing, something tells me that there must be something to this or I wouldn't have a good 50% of developers jumping out of the woodwork yelling "POST is evil!!!!1111!!1" ;-)&lt;br /&gt;&lt;br /&gt;See? &lt;a href="http://cafe.elharo.com/web/rest-vs-soap-a-parable/"&gt;http://cafe.elharo.com/web/rest-vs-soap-a-parable/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So, I'm curious on which side I will fall.&lt;br /&gt;&lt;br /&gt;Let's see...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15527242-7241290794616628868?l=swingsetacid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/7241290794616628868/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15527242&amp;postID=7241290794616628868' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/7241290794616628868'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/7241290794616628868'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/2009/02/wcf-will-do-rest-of-it-for-you.html' title='WCF will do the REST of it for you...'/><author><name>Joshua Ewer</name><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-15527242.post-1806395152649020401</id><published>2009-02-18T21:55:00.001-08:00</published><updated>2009-02-18T21:57:54.995-08:00</updated><title type='text'>Okay, fine, it's a little creepy.</title><content type='html'>Kat von D just signed my copy of her book (at my request) as "the hostess cupcake with the mostest rump shake." It was for my wife. I promise.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_-aAqftrAWm4/SZz0k-xhyGI/AAAAAAAAAAs/vtNrj-VZUhE/s1600-h/photo.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5304383377298802786" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; WIDTH: 320px; CURSOR: hand; HEIGHT: 240px" alt="" src="http://3.bp.blogspot.com/_-aAqftrAWm4/SZz0k-xhyGI/AAAAAAAAAAs/vtNrj-VZUhE/s320/photo.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15527242-1806395152649020401?l=swingsetacid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/1806395152649020401/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15527242&amp;postID=1806395152649020401' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/1806395152649020401'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/1806395152649020401'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/2009/02/okay-fine-its-little-creepy.html' title='Okay, fine, it&apos;s a little creepy.'/><author><name>Joshua Ewer</name><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://3.bp.blogspot.com/_-aAqftrAWm4/SZz0k-xhyGI/AAAAAAAAAAs/vtNrj-VZUhE/s72-c/photo.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15527242.post-3836568642145798417</id><published>2009-02-17T17:00:00.000-08:00</published><updated>2009-02-17T17:10:01.857-08:00</updated><title type='text'>TFS just broke up with me, but we got back together.</title><content type='html'>If everyone else thinks like me, automated database builds are the holy grail of continuous integration tasks. If you're a .NET-ish shop like this one, your DBAs are attached at the hip and aren't some nebulous/grumpy/ponytailed group that exists solely to shoot down your ideas because "[insert anything but MSSSQL] doesn't think that way." So, they write code just like you.&lt;br /&gt;&lt;br /&gt;And, just like you, their code breaks. Only, because they hold the lifeblood (the data) in their purview, they also have the unique ability of completely screwing you over with a simple mistake. So, their code must be solid.&lt;br /&gt;&lt;br /&gt;So, the thesis: just because it's DDL, why can't I treat it just like compileable, and therefore, unit-testable, code?&lt;br /&gt;&lt;br /&gt;Fortunately, you can do this with TFS. It's a pain because of several known issues all nicely detailed &lt;a href="http://blogs.msdn.com/buckh/archive/2007/09/11/vsts-2005-and-2008-building-database-projects-with-team-build.aspx"&gt;here by Buck&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;After a little haggling over infrastructure to pay for another license for Team Edition and a mess of horrifically complex build scripting (see post title), merges to our database code now automagically kick off a test battery and deploy to our staging environment.&lt;br /&gt;&lt;br /&gt;The best part is, once our DBA(s) got wind of my plan, they put in their ideas and now are so excited to write unit tests. Bless their hearts. I'm excited that they're suddenly light years ahead of most database developers.&lt;br /&gt;&lt;br /&gt;I just pretend to not care so they won't ask for a raise ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15527242-3836568642145798417?l=swingsetacid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/3836568642145798417/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15527242&amp;postID=3836568642145798417' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/3836568642145798417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/3836568642145798417'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/2009/02/tfs-just-broke-up-with-me-but-we-got.html' title='TFS just broke up with me, but we got back together.'/><author><name>Joshua Ewer</name><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-15527242.post-1396369246162123171</id><published>2009-02-17T16:58:00.001-08:00</published><updated>2009-02-17T17:00:40.723-08:00</updated><title type='text'>*Another* Akai show</title><content type='html'>At the Acadia again.  This time, February 27th, 2009.  We open for Bella Koshka, so we go first this time.  Probably around 9PM. &lt;br /&gt;&lt;br /&gt;We'll also be on the radio (KFAI 90.3 or 106.7 FM) at 7:30 for a mini-interview. &lt;br /&gt;&lt;br /&gt;We'll also be playing a round of shows at the Fine Line sometime in March-April.  Yay.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15527242-1396369246162123171?l=swingsetacid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/1396369246162123171/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15527242&amp;postID=1396369246162123171' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/1396369246162123171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/1396369246162123171'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/2009/02/another-akai-show.html' title='*Another* Akai show'/><author><name>Joshua Ewer</name><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-15527242.post-8204656517237826096</id><published>2009-02-04T10:36:00.000-08:00</published><updated>2009-02-04T12:18:05.560-08:00</updated><title type='text'>Don't worry about it, it happens to everyone ...</title><content type='html'>Premature Optimization?&lt;br /&gt;&lt;br /&gt;&lt;a href="http://joelonsoftware.com/"&gt;Joel Spolsky&lt;/a&gt; put it amazingly well when he said, of developers, that "the best ones are an order of magnitude better than the average ones."  Completely agree with that.   However, the best ones oftentimes have the problem that they &lt;em&gt;know&lt;/em&gt; they're that much better than the guy in the next cube/desk/office/bottega. &lt;br /&gt;&lt;br /&gt;So, in an attempt to "enlighten" their peers, they build the Taj Mahal.  Unfortunately, they forget to also build the most important part of shelter, the roof.   They're so busy shining the marble on the doorstep they forget to look up and see that they forgot to put a door!&lt;br /&gt;&lt;br /&gt;Funny thing is, I always used to fall onto the idealist side of the fence.  I'm working with some guys that are so far to that side that I've had no choice but to become the pragmatist of the group to keep us grounded in reality. &lt;br /&gt;&lt;br /&gt;"Yes, we can make Service A talk to Service B and have it shoot confetti out when it's finished, but does anyone else actually want that?"  &lt;br /&gt;&lt;br /&gt;A lot to be said for our &lt;a href="http://learnsigma.com/six-sigma-lean-or-toc-what%E2%80%99s-the-difference/"&gt;Lean/TOC&lt;/a&gt; brethren . . .&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15527242-8204656517237826096?l=swingsetacid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/8204656517237826096/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15527242&amp;postID=8204656517237826096' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/8204656517237826096'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/8204656517237826096'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/2009/02/dont-worry-about-it-it-happens-to.html' title='Don&apos;t worry about it, it happens to everyone ...'/><author><name>Joshua Ewer</name><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-15527242.post-6209880836449669869</id><published>2009-02-02T12:57:00.000-08:00</published><updated>2009-02-02T13:01:00.763-08:00</updated><title type='text'>Akai Show!!!1111!!!eleventy-one</title><content type='html'>One last thing:&lt;br /&gt;&lt;br /&gt;Akai show this Friday nite. &lt;br /&gt;&lt;br /&gt;02/06/2009 - &lt;a href="http://www.acadiacafe.com/"&gt;Acadia Cafe &lt;/a&gt;- w/ Nee Nee. 9pm - Free! - All Ages&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15527242-6209880836449669869?l=swingsetacid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/6209880836449669869/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15527242&amp;postID=6209880836449669869' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/6209880836449669869'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/6209880836449669869'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/2009/02/akai-show1111eleventy-one.html' title='Akai Show!!!1111!!!eleventy-one'/><author><name>Joshua Ewer</name><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-15527242.post-348172510921906312</id><published>2009-02-02T12:56:00.001-08:00</published><updated>2009-02-02T12:57:44.967-08:00</updated><title type='text'>UPDATE:  stateless sessions</title><content type='html'>BTW, if you are using IStatelessSession on inserts to reduce overhead, keep in mind that you can't persist the top level of an object tree and expect it to persist any child objects.  you'll need to iterate over collections and explicitly persist them. &lt;br /&gt;&lt;br /&gt;Using plain 'ole ISession means you don't have to do this, but you pay with overhead....&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15527242-348172510921906312?l=swingsetacid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/348172510921906312/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15527242&amp;postID=348172510921906312' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/348172510921906312'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/348172510921906312'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/2009/02/update-stateless-sessions.html' title='UPDATE:  stateless sessions'/><author><name>Joshua Ewer</name><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-15527242.post-109937600502870076</id><published>2009-02-02T12:51:00.000-08:00</published><updated>2009-02-02T12:55:55.749-08:00</updated><title type='text'>Yes, nHibernate *does* make friends with legacy databases</title><content type='html'>Though, it would prefer not to.  I posted two questions on &lt;a href="http://stackoverflow.com/questions/497548/nhibernate-2-0-mapping-a-composite-id-and-many-to-one-relationship-causes-inv"&gt;stackoverflow&lt;/a&gt; related to composite-id and many-to-one relationships and no one took the bait, so it's obviously difficult enough that a random dev found it not worth their time to earn 5 rep points . . .&lt;br /&gt;&lt;br /&gt;Suffice to say, I am making some sweet magic with this.  I can't see why I'd ever write another data access layer again...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15527242-109937600502870076?l=swingsetacid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/109937600502870076/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15527242&amp;postID=109937600502870076' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/109937600502870076'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/109937600502870076'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/2009/02/yes-nhibernate-does-make-friends-with.html' title='Yes, nHibernate *does* make friends with legacy databases'/><author><name>Joshua Ewer</name><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-15527242.post-5284437739968750956</id><published>2009-01-07T09:10:00.000-08:00</published><updated>2009-01-07T12:33:09.547-08:00</updated><title type='text'>You can pry my sprocs from my cold, dead hands!</title><content type='html'>No, I don't really think that way. &lt;br /&gt;&lt;br /&gt;Still, given the bias MS devs usually have towards their precious stored procedures would make you think that, if ORMs will truly gain traction in mainstream development, you have to make it easy to map them to existing stored procedures.  Granted, there will have to be some limitations, but &lt;em&gt;please&lt;/em&gt; tell me it's not that hard.&lt;br /&gt;&lt;br /&gt;Well, it's not.  It's still a PITA, though.  Yay.  Cue nHibernate 2.0:&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15527242-5284437739968750956?l=swingsetacid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/5284437739968750956/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15527242&amp;postID=5284437739968750956' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/5284437739968750956'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/5284437739968750956'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/2009/01/you-can-pry-my-sprocs-from-my-cold-dead.html' title='You can pry my sprocs from my cold, dead hands!'/><author><name>Joshua Ewer</name><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-15527242.post-7854404931479024635</id><published>2009-01-05T09:02:00.001-08:00</published><updated>2009-01-05T09:08:27.670-08:00</updated><title type='text'>Duh.</title><content type='html'>&lt;div&gt;Why is it that, now, after 10 years of (professionally) developing software, did someone tell me you could see more code on your screen if you just rotated your monitor 90 degrees?&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;a href="http://2.bp.blogspot.com/_-aAqftrAWm4/SWI-PEPhJmI/AAAAAAAAAAk/EwJH9d5Eswg/s1600-h/screenshot.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5287857341044172386" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; WIDTH: 320px; CURSOR: hand; HEIGHT: 240px" alt="" src="http://2.bp.blogspot.com/_-aAqftrAWm4/SWI-PEPhJmI/AAAAAAAAAAk/EwJH9d5Eswg/s320/screenshot.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt;Please see post title for my emotional response to this revelation.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15527242-7854404931479024635?l=swingsetacid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/7854404931479024635/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15527242&amp;postID=7854404931479024635' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/7854404931479024635'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/7854404931479024635'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/2009/01/duh.html' title='Duh.'/><author><name>Joshua Ewer</name><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://2.bp.blogspot.com/_-aAqftrAWm4/SWI-PEPhJmI/AAAAAAAAAAk/EwJH9d5Eswg/s72-c/screenshot.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15527242.post-4998419723643492115</id><published>2008-12-29T15:27:00.001-08:00</published><updated>2008-12-29T15:33:36.424-08:00</updated><title type='text'>Using software factories does not mean you are lazy.  Just sneaky.</title><content type='html'>A couple issues I've encountered using the latest drop of MSFT's &lt;a href="http://msdn.microsoft.com/en-us/library/cc487895.aspx"&gt;Service Factory&lt;/a&gt; have seriously wracked my brain.  If you're working through the HOLS or trying to actually use this thing (I'm still firmly in the "it's worth it (sometimes) camp," this might save you some time:&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#ff0000;"&gt;Situation:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;When saving a service contract model, you get the "path is not of legal form" exception.&lt;/li&gt;&lt;/ul&gt;&lt;span style="color:#006600;"&gt;Possible Resolution:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;There's some serious lack of client-side validation.  Did you put a space in the name of your ssfproject file?  I didn't, but I &lt;em&gt;did&lt;/em&gt; rename it later.&lt;/li&gt;&lt;/ul&gt;&lt;span style="color:#ff0000;"&gt;Situation:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt; When generating an ASMX implementation project or service you get this message "A namespace does not directly contain members such as fields or methods."&lt;/li&gt;&lt;/ul&gt;&lt;span style="color:#006600;"&gt;Possible Resolution:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Dangit!  I was hoping someone could tell me.  I still don't know what's up with this one.  *Sigh*&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15527242-4998419723643492115?l=swingsetacid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/4998419723643492115/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15527242&amp;postID=4998419723643492115' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/4998419723643492115'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/4998419723643492115'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/2008/12/using-software-factories-does-not-mean.html' title='Using software factories does not mean you are lazy.  Just sneaky.'/><author><name>Joshua Ewer</name><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-15527242.post-519344423266260663</id><published>2008-12-24T10:05:00.001-08:00</published><updated>2008-12-24T10:31:22.937-08:00</updated><title type='text'>ORMs can do things quickly? Stateless activity with nHibernate 2.0</title><content type='html'>nHibernate does a great job of handling changes through the use of its &lt;a href="http://www.hibernate.org/hib_docs/v3/reference/en-US/html/architecture.html#architecture-overview"&gt;session architecture&lt;/a&gt;. One difficult thing to do is break the mental lock you have on the word "session," especially if you've done any ASP(.NET),JSP type work. Session is more conceptual in this world. A session in Hibernate only lives long enough to service a call between your consumer and the store. That might be just enough to hydrate your objects, or long enough manage changes in your CLR objects, then persist those changes to the store.&lt;br /&gt;&lt;br /&gt;So, what happens if you're just doing an insert? I don't really care about what's the in the database now, I just want to persist a new row there. There is a significant amount of overhead when building up a session, and if you're building something along the lines of a high-speed keying app, that's an issue (ORM detractors will being saying "shouldn't have picked an ORM" at this point.). One of the reasons you pick an ORM is that it manages a lot of changes, but that does require the use of caching and all the overhead that comes with that.&lt;br /&gt;&lt;br /&gt;I've scanned dozens of blogs and couldn't find a good answer to this (yet). Then, the IStatelessSession.&lt;br /&gt;&lt;br /&gt;The IStatelessSession doesn't do all of that work, therefore, much less overhead in the scenario where you want to do quick operations. Code might look a lot like this (once you have a concrete session factory established):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;NHibernatePerson person = new NhibernatePerson();&lt;br /&gt;person.Name = "Me";&lt;br /&gt;&lt;p/&gt;&lt;br /&gt;using (IStatelessSession session = &lt;br /&gt;&amp;nbsp;&amp;nbsp;sessionManager.OpenStatelessSession())&lt;br /&gt;using (ITransaction scopedTransaction = &lt;br /&gt;&amp;nbsp;&amp;nbsp;statelessSession.BeginTransaction())&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;session.Insert(person);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;scopedTransaction.Commit();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;P.S. Moments after posting this, I mentioned what I was looking for to someone online and was Im'd &lt;a href="http://nhforge.org/blogs/nhibernate/archive/2008/10/30/bulk-data-operations-with-nhibernate-s-stateless-sessions.aspx"&gt;this blog link&lt;/a&gt;. Dangit. With metrics and everything! Well played, Mr. Brion. Well played.&lt;br /&gt;&lt;br /&gt;BTW, in retribution, i stole your double using statement.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15527242-519344423266260663?l=swingsetacid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/519344423266260663/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15527242&amp;postID=519344423266260663' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/519344423266260663'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/519344423266260663'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/2008/12/orms-can-do-things-quickly-stateless.html' title='ORMs can do things quickly? Stateless activity with nHibernate 2.0'/><author><name>Joshua Ewer</name><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-15527242.post-808786631723441241</id><published>2008-12-22T14:18:00.000-08:00</published><updated>2008-12-22T15:40:52.779-08:00</updated><title type='text'>Wiring up nHibernate with Web Service Software Factory</title><content type='html'>The backstory:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;I'm in the (not?)unique situation where I need to start integrating multiple services and subsystems. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;I write .NET code. I'm not a MS zealot. In fact, I'm an &lt;a href="http://altdotnet.org/"&gt;ALT.NET &lt;/a&gt;fan.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;My boss, however, loves Java. A lot. He says "use JBoss ESB." I say "but, Biztalk? I know it!?" He says, "refer to previous statement."&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Exit Criteria:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Build some core data services. Purely persistance, no business rules.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Expose them in an interoperable way (DataSets &lt;em&gt;are&lt;/em&gt; the &lt;a href="http://www.hanselman.com/blog/ReturningDataSetsFromWebServicesIsTheSpawnOfSatanAndRepresentsAllThatIsTrulyEvilInTheWorld.aspx"&gt;spawn of Satan&lt;/a&gt;)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Add the minimal amount of code maintenance work. Note: this does not mean &lt;em&gt;lines&lt;/em&gt; of code, this means &lt;em&gt;amount of maintenance &lt;/em&gt;required.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;p&gt;Failed solution 1: &lt;a href="http://msdn.microsoft.com/en-us/library/cc487895.aspx"&gt;Web Services Software Factory&lt;/a&gt;?&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Use WSSF to create some nice looking schemas to expose to our service bus. Our database is less than optimal in its design, and i shouldn't be using the database as a model for my domain anyways.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;WSSF is pretty nifty. Designers are great (they don't scale up well, though). Some nitpicks (tons and tons of code, all generateable, I know, but see Exit Criteria #3).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;As great as the contracts are, I still have to write a ridiculous amount of data access code, or reuse the stuff I already have written (but don't really like)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Failed solution 2: Use &lt;a href="http://www.nhibernate.org/"&gt;nHibernate 2.0&lt;/a&gt;?&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Get &lt;a href="http://www.codesmithtools.com/"&gt;CodeSmith&lt;/a&gt;. Eric Smith is my hero.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Gen up a simple nHibernate layer on top of my database.  &lt;/li&gt;&lt;br /&gt;&lt;li&gt;IList&lt;t&gt; is not serializable. There are a &lt;em&gt;lot&lt;/em&gt; of them in my entities. nHibernate objects look too much like my database. Yes, I got what I asked for. But it's not what i wanted ;-)  Workarounds are possible, but even 1-to-1 object mappings are hard to get around because nHibernate loves its dynamic proxy generation (I do too.  Just not now.)   &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Conceptually, I am right there with the ORM tool.   However, it's pretty clear nHibernate is clearly not a good solution for my DTO needs.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Eureka! Use the tools to do what they are designed to do (duh.) WSSF helps me expose my service in a very agnostic (in comparison with other MS tools) way. nHibernate helps me avoid ever writing anything resembling a data adapter.  CodeSmith helps me tie these things together.  &lt;/p&gt;&lt;p&gt;so, it all looks like this (and works, BTW): &lt;/p&gt;&lt;p align="center"&gt;&lt;a href="http://3.bp.blogspot.com/_-aAqftrAWm4/SVAjr_gx7jI/AAAAAAAAAAM/139OH1gf69Y/s1600-h/data_services_photo.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5282761601595862578" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; WIDTH: 320px; CURSOR: hand; HEIGHT: 240px" alt="" src="http://3.bp.blogspot.com/_-aAqftrAWm4/SVAjr_gx7jI/AAAAAAAAAAM/139OH1gf69Y/s320/data_services_photo.jpg" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;technical detail to follow &lt;em&gt;after&lt;/em&gt; everyone is happy with it ;-)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15527242-808786631723441241?l=swingsetacid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/808786631723441241/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15527242&amp;postID=808786631723441241' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/808786631723441241'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/808786631723441241'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/2008/12/wiring-up-nhibernate-with-web-service.html' title='Wiring up nHibernate with Web Service Software Factory'/><author><name>Joshua Ewer</name><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://3.bp.blogspot.com/_-aAqftrAWm4/SVAjr_gx7jI/AAAAAAAAAAM/139OH1gf69Y/s72-c/data_services_photo.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15527242.post-7248277556051054863</id><published>2008-10-19T22:40:00.000-07:00</published><updated>2008-12-05T08:21:58.315-08:00</updated><title type='text'>Mafia (part 2!)</title><content type='html'>&lt;strong&gt;December 5th, 2008 6PM, game starts around 7/7:30 sharp - Call me for directions.&lt;/strong&gt; &lt;strong&gt;Bring a snack/drink/adult beverage to share. Changes to house rules below in &lt;span style="color:#ff0000;"&gt;RED&lt;/span&gt;.&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;Setup: &lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The group should sit in a circle so that everyone can see everyone else. One person acts as the moderator and does not play. All players close their eyes and the moderator selects four people, at random, from the group. These people are:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;Mafia 1&lt;/ul&gt;&lt;ul&gt;Mafia 2&lt;/ul&gt;&lt;ul&gt;The Detective&lt;/ul&gt;&lt;ul&gt;The Untouchable&lt;/ul&gt;&lt;strong&gt;&lt;span style="color:#ff0000;"&gt;Round 0:&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;span style="color:#ff0000;"&gt;This Ezra's idea. It's a good one. &lt;em&gt;Before&lt;/em&gt; beginning the game, the group has five minutes to deliberate over one person to eliminate. While this is painful for everyone, at least it gives everyone a fighting chance to make it through the first round.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Round 1: &lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The moderator asks everyone to close their eyes and look down. The moderator asks the two mafiosa to open their eyes and find each other. The moderator asks the mafiosa to agree upon a single player to eliminate. This should be done in complete silence, otherwise they put themselves at risk for exposure. &lt;span style="color:#ff0000;"&gt;Plus, you are sitting in a room with 20 other people. If you make a noise, or move too much, when selecting someone, people will notice! &lt;/span&gt;They then put their heads back down and close their eyes.&lt;br /&gt;&lt;br /&gt;The moderator asks the Detective to open their eyes. The detective should select a single player to "investigate." The moderator will then tell the detective whether the selected player is a member of the mafia or not. This should also be done in complete silence, as the mafia will want to eliminate the detective to protect themselves. The Detective then puts their head down and closes their eyes.&lt;br /&gt;&lt;br /&gt;The moderator will then ask the Untouchable to open their eyes. The Untouchable should select a single player to be protected from the mafia. If this same player is selected for elimination by the mafia, they will be saved. The moderator will not reveal which person the Untouchable has selected. The Untouchable will then close their eyes.&lt;br /&gt;&lt;br /&gt;The moderator will then ask all players to open their eyes and announce which player has been eliminated. If the Untouchable saved the same player that was eliminated, then the moderator will announce that no one was eliminated in this round. The group then has a maximum of 5 minutes to deliberate and determine which players are the mafiosa. People can make claims, false accusations, lie about their identity, make alliances, whatever they think will preserve themselves and help them to survive to the next round.&lt;br /&gt;&lt;br /&gt;The group must vote to eliminate one of their members. The goal is to eliminate one of the mafiosa. Mafia hopes that a civilian, untouchable, or especially, the detective, is eliminated. The rest of the group hopes that a mafia member is eliminated.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Subsequent rounds: &lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;The next rounds begin with the same process. Detectives can use their knowledge from the prior round in a number of ways. If they determine the identity of a mafia, they can either covertly try to get people to vote to kill that person by staging an argument as to why, or they can announce themselves as detective and state they know with certainty that the person is mafia. This is dangerous if both mafia still are alive since the detective risks being eliminated in the next round. However, if only one mafia is left then it can be a good way to end the game since the object is to eliminate both mafia.&lt;br /&gt;&lt;br /&gt;Once both mafia are eliminated the game ends and the moderator (or a new moderator) can start a new game. However, if one or two mafia still alive, the game continues as the citizens try to eliminate the mafia through the voting process and the mafia try to eliminated the citizens one by one until none are left. If only one mafia is alive and the game progresses to where there are only three players left, if the vote ends up eliminating a citizen (leaving only one mafia and one citizen) the second citizen automatically loses and the mafia win the game.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;House rules:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;While deception, reverse psychology, and cunning are the name of the game, please refrain from using statements like "swear to God," "promise on the Bible" because that either ruins the fun of tricking other people or, you know, compromises your relationship with God ;-)&lt;/ul&gt;&lt;ul&gt;&lt;br /&gt;The moderator reserves the right to remove/add rules (such as requiring those eliminated to reveal whether or not they are mafia) in order to make the game more fun, interesting, or aggravating.&lt;/ul&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;The moderator's decisions are final. &lt;span style="color:#ff0000;"&gt;Because we had some problems with everyone keeping quiet when it was the moderator's turn, we will introduce "The Cowbell." If the group doesn't come to order when asked, the moderator may ring "The Cowbell". The first person caught talking five seconds after the bell is rung is eliminated, regardless of their role in the game. Don't test the moderator. They are benevolent dictators.&lt;/span&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15527242-7248277556051054863?l=swingsetacid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/7248277556051054863/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15527242&amp;postID=7248277556051054863' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/7248277556051054863'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/7248277556051054863'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/2008/10/mafia.html' title='Mafia (part 2!)'/><author><name>Joshua Ewer</name><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-15527242.post-3332422783939993298</id><published>2008-10-09T12:11:00.000-07:00</published><updated>2008-10-09T13:36:15.073-07:00</updated><title type='text'>Generating Dynamic Types at Runtime Through Reflection in .NET</title><content type='html'>(I realize that I am terrible at blogging regularly).&lt;br /&gt;&lt;br /&gt;This is an old sample I worked out a few months back. Upon further review, I could probably have done something with XSLT and deserialization, but it was a concious effort to use reflection to emit some code. You can skip the background if you want to get straight to code, ya lazy jerks ;-)&lt;br /&gt;&lt;br /&gt;So, without further ado:&lt;br /&gt;&lt;br /&gt;Business Problem: Custom data needs to be visible to the user in a grid. No customization of code, pure data configuration.&lt;br /&gt;&lt;br /&gt;Assumptions: Use .NET WinForms stock controls. There is an existing business/entity object framework that should be altered as little as possible (ideal being no modifications at all). Object tree looks as such: &lt;ul&gt;&lt;li&gt;Person has a name. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Person has an address. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Person has business specific properties that are constant throughout all scenarios. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Person will have custom key/value pairs that are constructed from data at run time (therefore, we have a custom object we'll call "CustomEntity" that is basically an object holding key/value pairs). &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;If you want to slap this heirarchical structure on top of a DataGridView, that ain't gonna happen. I know there are a number of third-party controls that purport to do this (I love you too, Infragistics) but that's not possible in this scenario. So, if I can't build a fancy control easily, the alternate approach is to build a generic object (little g, but we'll get to that in a sec) to bind to a stock control.&lt;br /&gt;&lt;br /&gt;I know I may want to do this again, so let's abstract this with some sort of factory we'll call "TypeFactory." In real-life I'll put a constraint on this class to make sure I can only do this with certain classes that have the custom collection driving this need . . .&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color:#006600;"&gt;&lt;strong&gt;//for demo/reference's sake&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;pre&gt;public interface ICustomEntityHolder&lt;/pre&gt;&lt;pre&gt;{&lt;/pre&gt;&lt;pre&gt;  &lt;span style="color:#006600;"&gt;&lt;strong&gt;//structure to hold custom data&lt;/strong&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;  List &lt;&gt; &lt;customentity&gt; CustomEntityCollection{get; set;}&lt;/pre&gt;&lt;pre&gt; &lt;/pre&gt;&lt;pre&gt;  &lt;span style="color:#006600;"&gt;&lt;strong&gt;//method to lookup matching entry and return value&lt;/strong&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;  object GetCustomEntityValue(string key);&lt;/pre&gt;&lt;pre&gt; &lt;/pre&gt;&lt;pre&gt;  &lt;span style="color:#006600;"&gt;&lt;strong&gt;//method to save or overwrite key/value pair&lt;/strong&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;  void SetCustomEntityValue(string key, object value);&lt;/pre&gt;&lt;pre&gt; &lt;/pre&gt;&lt;pre&gt;  &lt;span style="color:#006600;"&gt;&lt;strong&gt;//need some way to seed the new type's instance with data&lt;/strong&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;  void SeedObjectData(object seed);&lt;/pre&gt;&lt;pre&gt;}&lt;/pre&gt;&lt;pre&gt; &lt;/pre&gt;&lt;pre&gt;public class CustomEntity&lt;/pre&gt;&lt;pre&gt;{&lt;/pre&gt;&lt;pre&gt;  public string Key;&lt;/pre&gt;&lt;pre&gt;  public object Value;&lt;/pre&gt;&lt;pre&gt;}&lt;/pre&gt;&lt;pre&gt; &lt;/pre&gt;&lt;pre&gt;public class Person : ICustomEntityHolder&lt;/pre&gt;&lt;pre&gt;{&lt;/pre&gt;&lt;pre&gt;  public string Name;&lt;/pre&gt;&lt;pre&gt;  public string Address;&lt;/pre&gt;&lt;pre&gt;  public List&lt;customentity&gt; CustomEntityCollection;&lt;/pre&gt;&lt;pre&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;pre&gt;public static Type CreateExtendedType &lt;&gt; &lt;t&gt;(T baseType) where T : ICustomEntityHolder&lt;br /&gt;{&lt;br /&gt;  string assemblyNameValue = typeof(T).Name + "&lt;span style="color:#cc0000;"&gt;ExtendedEmit&lt;/span&gt;";&lt;br /&gt;&lt;/pre&gt;&lt;pre&gt;  AssemblyName assemblyName = new AssemblyName();&lt;br /&gt;  assemblyName.Name = assemblyNameValue;&lt;/pre&gt;&lt;pre&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre&gt;  AssemblyBuilder ab = Thread.GetDomain().DefineDynamicAssembly(&lt;/pre&gt;&lt;pre&gt;    assemblyName, &lt;/pre&gt;&lt;pre&gt;    AssemblyBuilderAccess.Run);&lt;/pre&gt;&lt;pre&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre&gt;  ModuleBuilder moduleBuilder = ab.DefineDynamicModule(assemblyName.Name);&lt;br /&gt; &lt;/pre&gt;&lt;pre&gt;  &lt;strong&gt;&lt;span style="color:#006600;"&gt;//create a type that derives from base T&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;  TypeBuilder typeBuilder =&lt;br /&gt;    moduleBuilder.DefineType(&lt;br /&gt;    assemblyName.Name,&lt;br /&gt;    TypeAttributes.Class  TypeAttributes.Public,&lt;br /&gt;    typeof(T));&lt;/pre&gt;&lt;pre&gt; &lt;/pre&gt;&lt;pre&gt;&lt;strong&gt;&lt;span style="color:#006600;"&gt;  &lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="color:#006600;"&gt;//base T needs to have a constructor that takes a copy of itself&lt;br /&gt;  //TODO: best way to seed new object's data?&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;  ConstructorBuilder constructorBuilder =&lt;br /&gt;    typeBuilder.DefineConstructor(&lt;/pre&gt;&lt;pre&gt; MethodAttributes.Public, &lt;/pre&gt;&lt;pre&gt; CallingConventions.Standard, &lt;/pre&gt;&lt;pre&gt; new Type[0]);&lt;/pre&gt;&lt;pre&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre&gt;  ILGenerator ilGen = constructorBuilder.GetILGenerator();&lt;br /&gt;  ilGen.Emit(OpCodes.Ldarg_0); //this arg&lt;br /&gt;  ilGen.Emit(OpCodes.Call, typeof(T).GetConstructor(new Type[0]));&lt;br /&gt;  ilGen.Emit(OpCodes.Ret);&lt;/pre&gt;&lt;pre&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span style="color:#009900;"&gt;&lt;strong&gt;  //iterate through the collection and create a public property on the &lt;/strong&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style="color:#009900;"&gt;&lt;strong&gt;  //extended object that accesses the underlying collection&lt;/strong&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;  foreach(CustomEntity entity in baseType.CustomEntityCollection&lt;/pre&gt;&lt;pre&gt;  {&lt;br /&gt;     FieldBuilder fb = typeBuilder.DefineField(&lt;/pre&gt;&lt;pre&gt;   "_" + entity.Key, &lt;/pre&gt;&lt;pre&gt;   typeof(object), &lt;/pre&gt;&lt;pre&gt;   FieldAttributes.Private);&lt;br /&gt;    &lt;/pre&gt;&lt;pre&gt;     PropertyBuilder pb = typeBuilder.DefineProperty(&lt;/pre&gt;&lt;pre&gt;   entity.Key, &lt;/pre&gt;&lt;pre&gt;   PropertyAttributes.HasDefault, &lt;/pre&gt;&lt;pre&gt;   typeof(object), &lt;/pre&gt;&lt;pre&gt;   Type.EmptyTypes);&lt;br /&gt; &lt;/pre&gt;&lt;pre&gt;     ILGenerator propILGen;&lt;br /&gt;  &lt;/pre&gt;&lt;pre&gt;     &lt;strong&gt;&lt;span style="color:#009900;"&gt;//create a getter that calls the underlying custom entity getter&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;     MethodBuilder propGet = typeBuilder.DefineMethod(&lt;/pre&gt;&lt;pre&gt;   "get" + entity.Key, &lt;/pre&gt;&lt;pre&gt;       MethodAttributes.Public, &lt;/pre&gt;&lt;pre&gt;       typeof(object), &lt;/pre&gt;&lt;pre&gt;       Type.EmptyTypes);&lt;/pre&gt;&lt;pre&gt;&lt;br /&gt;     propILGen = propGet.GetILGenerator();&lt;br /&gt;  &lt;/pre&gt;&lt;pre&gt;     MethodInfo customGetter = typeof(T).GetMethod(&lt;/pre&gt;&lt;pre&gt;   "GetCustomEntityValue", &lt;/pre&gt;&lt;pre&gt;   new Type[] { typeof(string) });&lt;/pre&gt;&lt;pre&gt;&lt;br /&gt;     propILGen.Emit(OpCodes.Ldarg_0);&lt;br /&gt;     propILGen.Emit(OpCodes.Ldstr, entity.Key);&lt;br /&gt;     propILGen.Emit(OpCodes.Call, customGetter);&lt;br /&gt;     propILGen.Emit(OpCodes.Ret);&lt;br /&gt;  &lt;/pre&gt;&lt;pre&gt;     pb.SetGetMethod(propGet);&lt;/pre&gt;&lt;pre&gt;&lt;br /&gt;&lt;strong&gt;     &lt;span style="color:#009900;"&gt;//create a setter that calls the underlying custom entity setter&lt;/span&gt;&lt;/strong&gt;&lt;/pre&gt;&lt;pre&gt;     MethodBuilder propSet = typeBuilder.DefineMethod(&lt;/pre&gt;&lt;/pre&gt;&lt;pre&gt;      "set" + entity.Key, &lt;/pre&gt;&lt;pre&gt;        MethodAttributes.Public, &lt;/pre&gt;&lt;pre&gt;        null, &lt;/pre&gt;&lt;pre&gt;        new Type[] { typeof(object) });&lt;/pre&gt;&lt;pre&gt;&lt;br /&gt;     propILGen = propSet.GetILGenerator();&lt;/pre&gt;&lt;br /&gt;  &lt;pre&gt;     MethodInfo customSetter = typeof(T).GetMethod(&lt;/pre&gt;&lt;pre&gt;      "SetCustomEntityValue",&lt;br /&gt;     new Type[] { typeof(string), typeof(object) });&lt;/pre&gt;&lt;pre&gt;&lt;br /&gt;     propILGen.Emit(OpCodes.Ldarg_0);&lt;br /&gt;     propILGen.Emit(OpCodes.Ldstr, entity.Key);&lt;br /&gt;     propILGen.Emit(OpCodes.Ldarg_1);&lt;br /&gt;     propILGen.Emit(OpCodes.Call, customSetter);&lt;br /&gt;     propILGen.Emit(OpCodes.Ret);&lt;br /&gt;  &lt;/pre&gt;&lt;pre&gt;     pb.SetSetMethod(propSet);&lt;br /&gt;   }&lt;br /&gt; &lt;/pre&gt;&lt;pre&gt;   Type extendedType = typeBuilder.CreateType();&lt;br /&gt;   return extendedType;&lt;br /&gt;}&lt;/pre&gt;&lt;/pre&gt;&lt;/pre&gt;So, an example of typical usage would be as such:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Person person = new Person();&lt;/pre&gt;&lt;pre&gt;Type extendedPersonType = TypeFactory.CreateExtendedType(person);&lt;/pre&gt;&lt;pre&gt;object extendedPerson = Activator.CreateInstance(extendedPersonType);&lt;/pre&gt;&lt;pre&gt;&lt;strong&gt;&lt;span style="color:#006600;"&gt;//yes, you could do this through the ICustomEntityHolder interface&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;MethodInfo seedDataMethod =&lt;br /&gt;   extendedPersonType.GetMethod("&lt;span style="color:#990000;"&gt;SeedObjectData&lt;/span&gt;");&lt;/pre&gt;&lt;pre&gt;&lt;/span&gt;if (seedDataMethod != null)&lt;/pre&gt;&lt;pre&gt;{seedDataMethod.Invoke(extendedPerson, new object[] { person});}&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;br /&gt;As a result you get an instance of a new type, preserving the existing properties, but with new properties representing each of the custom entity objects in that collection. You could take this object, or a collection thereof, and bind to a DataGridView. Overworked? Perhaps. Cool? Definitely.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15527242-3332422783939993298?l=swingsetacid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/3332422783939993298/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15527242&amp;postID=3332422783939993298' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/3332422783939993298'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/3332422783939993298'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/2008/10/generating-dynamic-types-at-runtime.html' title='Generating Dynamic Types at Runtime Through Reflection in .NET'/><author><name>Joshua Ewer</name><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-15527242.post-874338691072380949</id><published>2007-05-24T10:30:00.000-07:00</published><updated>2007-05-24T10:36:45.346-07:00</updated><title type='text'>Lost.</title><content type='html'>Lost.&lt;br /&gt;&lt;br /&gt;I wanted my pants to be forcibly blown off by the awesomeness of the finale.&lt;br /&gt;&lt;br /&gt;You failed.&lt;br /&gt;&lt;br /&gt;Then, this morning I woke up and realized that they were subtley removed throughout the course of my brain digesting the previous night's events.&lt;br /&gt;&lt;br /&gt;Touché, lost, touché.&lt;br /&gt;&lt;br /&gt;Consider myself humbled by your grandeur. Again.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15527242-874338691072380949?l=swingsetacid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/874338691072380949/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15527242&amp;postID=874338691072380949' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/874338691072380949'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/874338691072380949'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/2007/05/lost.html' title='Lost.'/><author><name>Joshua Ewer</name><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-15527242.post-3005309500827761634</id><published>2007-05-22T11:42:00.000-07:00</published><updated>2007-05-22T12:08:28.719-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='musings'/><title type='text'>not so bad?</title><content type='html'>I was watching an interesting podcast (&lt;a href="http://revision3.com/diggnation"&gt;http://revision3.com/diggnation&lt;/a&gt;) related to trademarks. Sometimes you just hate the larger companies (think LucasFilm, though they're a poor example since they've supported fan films before) stomping all over the kid that makes a fan film in his basement.&lt;br /&gt;&lt;br /&gt;Turns out, though, I have a new appreciation for the need to do so. If you don't aggressively protect your trademark and allow it to be come co-opted by another party, you can lose the rights to the trademark.&lt;br /&gt;&lt;br /&gt;Case in point, someone had created some tools for digg and used "digg" in the product name. By doing so, even though digg may not have cared, had no choice but to send out a cease-and-desist in order to protect its rights. I may hate lawyers and the legal system in general (despite designing software for a claims administration company) but it makes me wonder how many other seemingly unfair practices occur in the business world that are easily justified from someone's perspective. It *almost* makes me feel bad for the RIAA . . . *almost*&lt;br /&gt;&lt;br /&gt;Anyways, this thought process made me think about my lack of online presence.  Some "pizza slut" (hey, she used it to describe herself) stole my "swingsetacid" name and used it on myspace.   now, hey, it came from a GYBE! song title, so i can't claim ownership.  and our above mentioned friend does list GYBE! as a musical interest.  still, it's not like googling "swingsetacid" will bring up anything but something related to me.  so, i figure, i should probably continue to post some interesting things as i have time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15527242-3005309500827761634?l=swingsetacid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/3005309500827761634/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15527242&amp;postID=3005309500827761634' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/3005309500827761634'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/3005309500827761634'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/2007/05/not-so-bad.html' title='not so bad?'/><author><name>Joshua Ewer</name><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-15527242.post-112431637677931781</id><published>2005-08-17T15:05:00.000-07:00</published><updated>2005-08-17T15:06:16.783-07:00</updated><title type='text'>::swingsetacid:: v.3.0</title><content type='html'>why go through the hassle of paying for your own host and writing your own blogger when you can use this place?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15527242-112431637677931781?l=swingsetacid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swingsetacid.blogspot.com/feeds/112431637677931781/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15527242&amp;postID=112431637677931781' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/112431637677931781'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15527242/posts/default/112431637677931781'/><link rel='alternate' type='text/html' href='http://swingsetacid.blogspot.com/2005/08/swingsetacid-v30.html' title='::swingsetacid:: v.3.0'/><author><name>Joshua Ewer</name><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></feed>
