<?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'><id>tag:blogger.com,1999:blog-24760385</id><updated>2010-01-15T14:13:17.258-08:00</updated><title type='text'>NET Progress</title><subtitle type='html'>John Rusk's notes on .NET Programming</subtitle><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default?start-index=26&amp;max-results=25'/><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://dotnet.agilekiwi.com/blog/atom.xml'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>47</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-24760385.post-5371946381729804330</id><published>2010-01-15T14:08:00.000-08:00</published><updated>2010-01-15T14:13:17.272-08:00</updated><title type='text'>Debugging IEnumerable</title><content type='html'>I often find enumerables difficult to inspect in the debugger.  Here's a trick I just discovered.&lt;br /&gt;&lt;br /&gt;Given:&lt;br /&gt;&lt;br /&gt;IEnumerable&lt;SomeType&gt; foo = ...&lt;br /&gt;&lt;br /&gt;you can inspect it more easily by first writing this in the Immediate Window:&lt;br /&gt;&lt;br /&gt;foo = foo.ToList()&lt;br /&gt;&lt;br /&gt;Press Enter in the immediate window, and foo changes from a (lazily) evaluated list (which is hard to inspect) into a real List&lt;SomeType&gt; which you can easily inspect by just hovering over it's Non-public members -&gt; items.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/24760385-5371946381729804330?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/5371946381729804330/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2010/01/debugging-ienumerable.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/5371946381729804330'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/5371946381729804330'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2010/01/debugging-ienumerable.html' title='Debugging IEnumerable&lt;T&gt;'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-24760385.post-8770506694354293482</id><published>2009-10-25T17:57:00.000-07:00</published><updated>2009-10-25T18:05:17.118-07:00</updated><title type='text'>Exporting High-Res Graphics from Excel</title><content type='html'>&lt;p&gt;I've recently been battling with technology, trying to save some Excel charts as high-res (900 dpi) files.&lt;/p&gt;&lt;p&gt;Here's the technique I finally came up with.  (It also works for PowerPoint slides).:&lt;/p&gt;&lt;p&gt;1. Save the chart as a PDF from Office (The PDF output is vector-based, so is very high quality)&lt;/p&gt;&lt;p&gt;2. Use a command line line, this, to use Ghostscript to convert the PDF to a suitable tiff file.  (In my case, I want the final images to be 4 inches wide, at 900 dpi, but here I have specified an output size of 5 inches (72 * 5 = 360), then I'll crop the images back to 4in in the next step.)&lt;/p&gt;&lt;p&gt;gswin32c -dSAFER -dBATCH -dNOPAUSE -sFONTPATH="E:\windows\fonts" -sDEVICE=tiffgray -r900 -dDEVICEWIDTHPOINTS=360 -dDEVICEHEIGHTPOINTS=221  -dPDFFitPage -sOutputFile=%~n1.tiff %1&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Key parameters are -dPDFFitPage, to cause resizing when using PDFs ans input, the DEVICExPOINTS to set the size of the output in points (1/72 ths of an inch), and -r to set the DPI.&lt;/p&gt;&lt;p&gt;3. Finally, open the tiff in Photoshop (or similar) to crop and make any other final adjustments, then save from Photoshop.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/24760385-8770506694354293482?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/8770506694354293482/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2009/10/exporting-high-res-graphics-from-excel.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/8770506694354293482'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/8770506694354293482'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2009/10/exporting-high-res-graphics-from-excel.html' title='Exporting High-Res Graphics from Excel'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-24760385.post-3725162168224756516</id><published>2009-08-31T02:12:00.000-07:00</published><updated>2009-08-31T02:23:01.542-07:00</updated><title type='text'>Fix the Cross Functional Button on Toshiba Portege M200</title><content type='html'>I recently bought a second-hand Toshiba M200 tablet PC.  It's great!&lt;br /&gt;&lt;br /&gt;I just had one problem, the little 4-way button, which looks like a mini joystick and is technically known as the "Cross Functional Button", basically didn't work.  It was more of a non-functional button, really.&lt;br /&gt;&lt;br /&gt;It is supposed to allow you to scroll in all 4 directions, which is a very important thing when in tablet mode, because you don't have access to the keyboard.  But, it just output numbers instead of scrolling.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I searched and searched and found nothing particularly helpful.  Eventually I went to the Toshiba site, found the "Toshiba Tablet PC Buttons Driver", installed it, and my problem was solved! &lt;/p&gt;&lt;p&gt;I have no idea why, out of all the pages I searched, no-one mentioned this.  I found one where someone had the exact same problem, but resorted to a much more complicated solution.  So, this post is here for the next person who has the same problem.  Hopefully, you'll find this post and save yourself the hours of frustration that I had.  Just install the driver ;-)&lt;/p&gt;&lt;p&gt;PS while you're there, install the accelerometer driver too, if you have &lt;a href="http://www.technologyquestions.com/technology/windows-xp-tablet-pc-newsgroup/2877-screen-orientation.html"&gt;this&lt;/a&gt; problem.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/24760385-3725162168224756516?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/3725162168224756516/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2009/08/fix-cross-functional-button-on-toshiba.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/3725162168224756516'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/3725162168224756516'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2009/08/fix-cross-functional-button-on-toshiba.html' title='Fix the Cross Functional Button on Toshiba Portege M200'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-24760385.post-5164363880808405326</id><published>2009-01-31T12:30:00.000-08:00</published><updated>2009-01-31T14:04:30.576-08:00</updated><title type='text'>Things I'd like to see in the Entity Framework</title><content type='html'>With the announcement that the Entity Framework (aka EF or LINQ to Entities) &lt;a href="http://dotnet.agilekiwi.com/blog/2008/11/future-of-linq-to-sql.html"&gt;will become&lt;/a&gt; the favoured Microsoft ORM, many people have blogged about how important it will be for EF to achieve better ease-of-use in .NET 4.0.&lt;br /&gt;&lt;p&gt;I'd like to add my 2c worth on what I think EF should include. (By the way, I've never worked with EF, and won't until at least the .NET 4 version, so for all I know some of these things might be present already. Basically, this list is my attempt to capture some of the lesser-known lessons learned from using LINQ to SQL.)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;1. Metamodel&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;An acccessible metamodel that is at least as capable as that in LINQ to SQL (i.e. &lt;a href="http://msdn.microsoft.com/en-us/library/system.data.linq.mapping.metamodel.aspx"&gt;MetaMode&lt;/a&gt;l and friends). On my current project the metamodel has saved us over and over again - allowing us to &lt;a href="http://dotnet.agilekiwi.com/blog/2008/11/linq-to-sql-presentation.html"&gt;do things that we needed&lt;/a&gt; but couldn't do with just the basic generated entities. I think it's extremely important to have this kind of "back door" that lets programmers step outside of the POCO model and access mapping-related state and metadata.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;2. Lifecyle information in constructor&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;A way to tell the difference between explicit construction of an object in code, verus construction by EF as the object is loaded out of the database. This is a gap that we've seen in LINQ to SQL. There are partial methods for various parts of the object lifecyle (such as creation and pre-save validation) but there is no way to tell whether the creation event is happening due to a load from the database, or the "new"-ing of an instance by application code. It seems wrong to have a full set of "hooks" into the object lifecycle &lt;em&gt;except&lt;/em&gt; for this. &lt;/p&gt;&lt;p&gt;My suggestion would be to have the generated entity class include two constructors. One would be a parameterised constructor. Its parameter would be an enum that indicates whether creation is due to loading or some other reason. E.g. &lt;/p&gt;&lt;p&gt;public Person(CreationContext context)&lt;/p&gt;&lt;p&gt;{.. } &lt;/p&gt;&lt;p&gt;where context may be something CreationContext.NewInstance or CreationContext.Loading&lt;/p&gt;&lt;p&gt;The other generated constructor would simply look like this&lt;/p&gt;&lt;p&gt;public Person():this(CreationContext.NewInstance)&lt;/p&gt;&lt;p&gt;{...}&lt;/p&gt;&lt;p&gt;So, when we write "new Person()" in code, the parameterless constructor passes the NewInstance parameter through to the "real" constructor. When the framework loads an object from the database, it should call the parameterized constructor directly, passing CreationContext.Loading. Then, at construction time, the object can always tell the purpose for which it is being constructed: does it represent a brand-new entity, or is it, conceptually, an existing entity which is being "deserialized" from the database?&lt;/p&gt;&lt;p&gt;The most obvious use for this is objects which, when created, should always have particular child objects. &lt;a href="http://social.msdn.microsoft.com/forums/en-US/linqtosql/thread/ed497bcc-0d3c-4de8-8f7b-fe432e8f258e/"&gt;E.g. an order that always has at least one order line&lt;/a&gt;. If the order doesn't know why it's constructor has been called, then it cannot go ahead and make a default child instance - one might already exist in the database in the CreationContext.Loading scenario.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;3. Don't presume or require a big impedance mismatch&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;There are some advantages to LINQ to SQL's very direct mapping approach. In particular, because the database is virtually identical to the object model the team only has to learn, understand and remember &lt;em&gt;one&lt;/em&gt; model. The means that &lt;a href="http://jamesshore.com/Agile-Book/ubiquitous_language.html"&gt;Ubiquitous Language&lt;/a&gt; extends all the way down to the database. (Particularly important if SQL, rather than objects, will be the basis for report generation; but still useful even if you're not doing SQL reporting, IMHO.)&lt;/p&gt;&lt;p&gt;As soon as you get the complex mappings, which are touted as an advantage of EF, the team has to understand &lt;em&gt;two&lt;/em&gt; models, &lt;em&gt;and&lt;/em&gt; the relationship between them. &lt;/p&gt;&lt;p&gt;In some applications, such mapping is indeed necessary. Perhaps an existing database doesn't match good object design; or the object design is complex enough to require non-trival mappings. &lt;/p&gt;&lt;p&gt;However, in projects where the same team is building the application and database from scratch, and where the object model is not too complex, it can be a good thing to have a simple mapping that's virtually one-to-one. EF should allow this, and the EF documentation should present it as a valid option. &lt;/p&gt;&lt;p&gt;&lt;strong&gt;4. Hand-writable entities&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Property getters and setters, on domain entities, should be simple enough to write by hand. This can be done by some kind of AOP (to inject "smarts" into ordinary-looking properties) or by &lt;a href="http://www.codeplex.com/ActiveSharp"&gt;ActiveSharp&lt;/a&gt;. LightSpeed is a good example of an ORM in which all the "smarts" of property setting and getting reside behind &lt;a href="http://www.mindscape.co.nz/blog/?p=64"&gt;simple hand-writable properties&lt;/a&gt;. &lt;/p&gt;&lt;p&gt;[Disclaimer: I wrote ActiveSharp and Lighspeed (optionally) uses it. My point here is not to promote my own code, but to promote the idea that entity properties should be concise. Concise properties, whether hand-written or codegen'd, make the code much easier to work with.]&lt;/p&gt;&lt;p&gt;&lt;strong&gt;5. Object relationships should be able to span diagrams (and assemblies)&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;An annoying limitation of LINQ to SQL (&lt;a href="http://www.thedatafarm.com/blog/CommentView,guid,d3e59302-828b-4c02-ba89-9a1916465529.aspx"&gt;and LINQ to Entities&lt;/a&gt;) is that, in practice, all your entities must be in one designer diagram. I say that because, if they are not in one diagram, then you can't have meaningful relationships (and lazy loading) between objects in different diagrams. &lt;/p&gt;&lt;p&gt;This relates to point 4, above. If properties are simple enough to write by hand, then you can use several different diagrams and then "stitch them together" using hand-coded relationship properties.&lt;/p&gt;&lt;p&gt;E.g. you might have one diagram focusing on enties related to sales, and another on entities related to production. For the (hopefully few) relationships that go from entities in the Sales diagram to entities in the Production diagram, you can create them by hand as long as hand-authoring is a viable option.&lt;/p&gt;&lt;p&gt;I'm planning to do this on my current LINQ to SQL project, possibly using some of &lt;a href="http://www.codeplex.com/Close2Poco"&gt;this&lt;/a&gt; code.&lt;/p&gt;&lt;p&gt;Finally, such a solution should not just allow entities to be defined on different diagrams, but also for those diagrams (and their generated entities) to be in different assemblies/projects.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Well, that's the end of my 2c worth.... for now ;-)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/24760385-5164363880808405326?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/5164363880808405326/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2009/01/things-id-like-to-see-in-entity.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/5164363880808405326'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/5164363880808405326'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2009/01/things-id-like-to-see-in-entity.html' title='Things I&apos;d like to see in the Entity Framework'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-24760385.post-6810272598705132144</id><published>2008-12-02T00:19:00.001-08:00</published><updated>2009-01-31T12:28:19.464-08:00</updated><title type='text'>What's up with P&amp;P?</title><content type='html'>What's up with the interface between Microsoft's Patterns and Practices group (P&amp;P) and the wider community?&lt;br /&gt;&lt;br /&gt;P&amp;P are writing a new version of their guidance for architecture on the Microsoft platform, and they're asking for community feedback.  But by and large the community isn't giving any!  And, when feedback is offered, P&amp;P aren't necessarily replying.  &lt;br /&gt;&lt;br /&gt;For instance: &lt;br /&gt;&lt;br /&gt;After the P&amp;P Knowledge base project had been up for about 2 months, I &lt;a href="http://codebetter.com/blogs/jeremy.miller/archive/2008/09/11/p-amp-p-architectural-guidance-version-2.aspx#184256"&gt;counted&lt;/a&gt; exactly &lt;span style="font-style:italic;"&gt;three&lt;/span&gt; meaningul comments on the substance of what MS had written.  Of those three comments, two were from me(!), and to this day those two &lt;a href="http://www.codeplex.com/AppArch/Thread/View.aspx?ThreadId=39113"&gt;remain unanswered&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;Confusingly, there are now three different CodePlex projects in which P&amp;P are seeking community input.  There's the &lt;a href="http://www.codeplex.com/AppArch"&gt;App Arch Guide knowledge base&lt;/a&gt;, the &lt;a href="http://www.codeplex.com/AppArchGuide"&gt;App Arch Guide Book&lt;/a&gt;, and the &lt;a href="http://www.codeplex.com/AppArchContrib"&gt;App Arch Community Contribution project&lt;/a&gt; (which, as if to prove my point, is completely empty)!&lt;br /&gt;&lt;br /&gt;So, community, &lt;span style="font-style:italic;"&gt;what's up!&lt;/span&gt; Has no-one got &lt;span style="font-style:italic;"&gt;anything&lt;/span&gt; to say about architecture!!!!&lt;br /&gt;&lt;br /&gt;And Microsoft, what's up with you?  What are you doing to make this work?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Update 1 Feb 08:&lt;/span&gt; Microsoft recently contacted me to follow up on my questions.  Thanks :-)  As much as I appreciate that contact (and I do) the overall lack of engagement seems to remain.  I still don't see much meaningful involvement from/with the community.  The &lt;a href="http://www.codeplex.com/AppArchContrib"&gt;Community Contribution project&lt;/a&gt; is still empty, except for a brief statement of it's purpose, which has only been &lt;span style="font-style:italic;"&gt;read&lt;/span&gt; 38 times.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/24760385-6810272598705132144?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/6810272598705132144/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/12/whats-up-with-p.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/6810272598705132144'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/6810272598705132144'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/12/whats-up-with-p.html' title='What&apos;s up with P&amp;P?'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-24760385.post-3253940569594423776</id><published>2008-11-18T22:48:00.000-08:00</published><updated>2008-11-18T23:05:40.058-08:00</updated><title type='text'>Hosting a window from one process inside another</title><content type='html'>Every time this topic comes up, I seem to have lost my bookmarks on it. So, here's a blog entry so I won't lose them again...&lt;br /&gt;&lt;br /&gt;Under Windows it is possible to visually "dock" the main window of one process inside a Window belonging to another process.  You get the visual effect of one program, but there are still two completely separate exes involved.&lt;br /&gt;&lt;br /&gt;I once used this to "host" an EXE inside Internet Explorer.  We wrote a little tiny ActiveX (this was in the dark ages before managed code). All the ActiveX did was start our EXE, and then "dock" the EXE's main window inside the client area of the ActiveX.  It &lt;span style="font-style:italic;"&gt;looked&lt;/span&gt; like our EXE &lt;span style="font-style:italic;"&gt;was&lt;/span&gt; the ActiveX - but our EXE had no idea that any of this was going on.  It just doing its thing, running as an independent process.&lt;br /&gt;&lt;br /&gt;The secret is the Windows API function SetParent. You can use it to set a window from process A as the parent of the main window of process B.&lt;br /&gt;&lt;br /&gt;I haven't done this for a while.  As I recall you need to make another call to make the hosted window look like a borderless child window (SetWindowLong IIRC) and I think I also had to detect resising of the "host" and programatically resize the child.&lt;br /&gt;&lt;br /&gt;Here are some links on the subject, following a rather brief Google:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://geekswithblogs.net/gyoung/archive/2006/04/26/76521.aspx"&gt;http://geekswithblogs.net/gyoung/archive/2006/04/26/76521.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.codeguru.com/forum/showthread.php?threadid=234862"&gt;http://www.codeguru.com/forum/showthread.php?threadid=234862&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.codeproject.com/KB/miscctrl/winwordcontrol.aspx"&gt;http://www.codeproject.com/KB/miscctrl/winwordcontrol.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I'm fairly sure I learnt this technique from something on Microsoft's site, in about 2000.  But &lt;a href="http://blogs.msdn.com/johnrdurant/archive/2006/01/23/host-word-winform.aspx"&gt;this post&lt;/a&gt; says they are no longer recommending it (at least, not for hosting Office apps) so perhaps that explains why I can't find the original MS post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/24760385-3253940569594423776?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/3253940569594423776/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/11/hosting-window-from-one-process-inside.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/3253940569594423776'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/3253940569594423776'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/11/hosting-window-from-one-process-inside.html' title='Hosting a window from one process inside another'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-24760385.post-4072771872732786301</id><published>2008-11-03T23:51:00.001-08:00</published><updated>2008-11-04T00:38:56.245-08:00</updated><title type='text'>LINQ to SQL Presentation</title><content type='html'>Here is a copy of the presentation I have at the 2008 Christchurch Code Camp. (&lt;a href="http://dotnet.agilekiwi.com/LinqToSql-JohnRusk.ppt.zip"&gt;zipped ppt&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;One of the key points of the presentation was to cover what LINQ to SQL includes, both out-of-the-box, and with the additions that we have been able to build on top of it at &lt;a href="http://www.optimation.co.nz/"&gt;Optimation&lt;/a&gt;. I put together the list that follows from two sources: Ayende's list of &lt;a href="http://ayende.com/Blog/archive/2006/05/12/25ReasonsNotToWriteYourOwnObjectRelationalMapper.aspx"&gt;25 things your OR Mapper must do&lt;/a&gt;; plus other things that we found useful. Ayende's points are in normal font; my additions to his is are shown in italics.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Out of the box, you get:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;CRUD and querying&lt;br /&gt;Transactions&lt;br /&gt;(Bi-directional) associations&lt;br /&gt;Lazy loading&lt;br /&gt;Polymorphic queries (single-table inheritance only)&lt;br /&gt;"Dirty Tracking" with ability to return full change set&lt;br /&gt;Loading properties without loading whole object&lt;br /&gt;Identity Map&lt;br /&gt;Concurrency Control&lt;br /&gt;Acceptable debuggability&lt;br /&gt;Safe multi-threading (1 datacontext = 1 user on 1 thread is the general rule of thumb)&lt;br /&gt;Well-defined exception policy&lt;br /&gt;Lifecycle events (create/update etc)&lt;br /&gt;Composite primary keys&lt;br /&gt;Automatic dependency ordering when saving changes&lt;br /&gt;Paging support (via Skip/Take)&lt;br /&gt;Aggregation support (group/max/min etc)&lt;br /&gt;&lt;em&gt;Original value tracking&lt;/em&gt;&lt;br /&gt;&lt;em&gt;Property change notifications&lt;/em&gt;&lt;br /&gt;&lt;em&gt;Runtime SQL logging&lt;/em&gt;&lt;br /&gt;&lt;em&gt;Ability to generate database from object model&lt;/em&gt;&lt;br /&gt;&lt;em&gt;Persistence by reachabilty&lt;/em&gt;&lt;br /&gt;&lt;em&gt;Enhanced "reflection" via LINQ to SQL MetaModel&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;With our add-ons to LINQ to SQL you (or at least we ;-) also get&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Undo (both to "as fetched" and "current DB state")&lt;br /&gt;Flexible eager load&lt;br /&gt;&lt;em&gt;Unit testability&lt;/em&gt;&lt;br /&gt;&lt;em&gt;Test: is this object new?&lt;/em&gt;&lt;br /&gt;&lt;em&gt;Check mapping against DB&lt;/em&gt;&lt;br /&gt;&lt;em&gt;In-memory savepoints (like DB savepoints, but for in-memory entities which haven't been saved yet)&lt;/em&gt;&lt;br /&gt;&lt;em&gt;Proper serialization of entities (none of the usual LINQ to SQL serialization restrictions)&lt;/em&gt;&lt;br /&gt;&lt;em&gt;Clone trees of related entities (clone parent with children)&lt;/em&gt;&lt;br /&gt;&lt;em&gt;Delete-any-object (even if is a new unsaved one; automatically sever relationships to other objects)&lt;/em&gt;&lt;br /&gt;&lt;em&gt;Get data context from object (based on &lt;/em&gt;&lt;a href="http://www.lowendahl.net/showShout.aspx?id=185"&gt;&lt;em&gt;this&lt;/em&gt;&lt;/a&gt;&lt;em&gt; with only very minor changes)&lt;/em&gt;&lt;br /&gt;&lt;em&gt;Get reachable objects (approximates "find me all objects in the datacontext)&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;You get only limited support for:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Caching at unit-of-work (datacontext) level&lt;br /&gt;Custom field types (limited to built-in types, enums, xml, .Parse()-able strings and binary ISerializable. &lt;a href="http://msdn.microsoft.com/en-us/bb386947.aspx"&gt;Here&lt;/a&gt; is the valuable and hard-to-find reference page)&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;You get no support at all for:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Caching at application-wide level (other than that which is done for you by SQL Server itself)&lt;br /&gt;Cache invalidation policies&lt;br /&gt;Update batching&lt;br /&gt;Cascading update/delete in object model (must rely on DB to do this instead, if you want it)&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;br /&gt;All in all, its a fairly strong list. Stronger, I suspect, than many people expect.&lt;br /&gt;&lt;br /&gt;As for the rest of the presentation, some of it will make sense from written slides, and some won't ;-) A couple of notes here might help:&lt;ul&gt;&lt;li&gt;The solution to comments on entity properties, and refreshing the designer, can be found &lt;a href="http://blog.huagati.com/res/index.php/cat/tools/"&gt;here&lt;/a&gt;. It looks real good, although I haven't got round to trying it yet myself.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Here are the hyperlinks to the &lt;a href="https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=343378"&gt;change set&lt;/a&gt; and &lt;a href="https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=376669"&gt;association bugs&lt;/a&gt;. NOTE: Microsoft have just announced that they will fix the latter in .NET 4.0, which goes to prove that they really are going to include LINQ to SQL fixes in that release.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;br /&gt;Using the "mapping checker" code. These three points will help if you want to use it: LinqUtil.GetModel is our wrapper for MappingSource.GetModel() - see later slides for details; LinqUtil.IsMappedType() is our wrapper for calling IsEntity on a metaType returned from the MetaModel; and Uow.All(type) is our wrapper for DataContext.GetTable(type). Simply copy the code, replacing our wrappers as noted above.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;That's all for now. As noted in the presentation, please do comment below or email me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/24760385-4072771872732786301?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/4072771872732786301/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/11/linq-to-sql-presentation.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/4072771872732786301'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/4072771872732786301'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/11/linq-to-sql-presentation.html' title='LINQ to SQL Presentation'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-24760385.post-1829171684730202341</id><published>2008-11-02T01:21:00.000-07:00</published><updated>2008-11-02T01:24:50.266-08:00</updated><title type='text'>Future of LINQ to SQL</title><content type='html'>Yesterday, I did a presentation on LINQ to SQL.   At about the time I was talking about how great it was, Microsoft was announcing that LINQ to SQL will not be their recommended solution in .NET 4!  They will be recommending LINQ to Entities instead.&lt;br /&gt;&lt;p&gt;Here, in no particular order, are some intial thoughts:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Sorry I wasn't well-informed enough to mention this at the presentation!  It seems like the news hit the net after I left for the Code Camp.  I did hear there'd been speculation from outside Microsoft, but I mistakenly dismissed it as an over-reaction to the recent emphasis on Entity Framework. &lt;br /&gt;&lt;/li&gt;&lt;li&gt;The news is not as bad as it sounds.  The best post on the topic seems to be this one: &lt;a href="http://damieng.com/blog/2008/10/31/linq-to-sql-next-steps"&gt;http://damieng.com/blog/2008/10/31/linq-to-sql-next-steps&lt;/a&gt;.  &lt;em&gt;Read that post now, if you have not done so already.&lt;/em&gt;  Basically, LINQ to SQL will still be available and there will even be improvements and bug fixes.  In particular "we [Microsoft] are going to make sure LINQ to SQL continues to operate as it should. This doesn’t just mean making sure what we had works in .NET 4.0 but also fixing a number of issues that have arisen as people pick it up for more advanced projects and put it into production environments".&lt;/li&gt;&lt;li&gt;To successfully execute this strategy, Microsoft will have to bring the best of LINQ to SQL to LINQ to Entities - in particular, they will have to bring lightness, speed and simplicity to cases where the mapping is simple and relatively direct.  I hope the &lt;a href="http://andrewpeters.net/2008/09/02/joining-microsoft/"&gt;recent addition of Andrew Peters&lt;/a&gt; to the team will help in that regard, due to his experience on Mindscapes' &lt;a href="http://www.mindscape.co.nz/products/LightSpeed/default.aspx"&gt;LightSpeed&lt;/a&gt; ORM.   &lt;/li&gt;&lt;li&gt;I think it will be very important for LINQ to Entities to expose the equivalent of LINQ's MetaModel - complete with the ability to use it to implement workarounds, as I demonstrated in my presentation.  (We use the MetaAccessors to do all kinds of things). We've been able to use it plug virtually all the "holes" we've found in LINQ to SQL, and a similar capability is a must in LINQ to Entities if it is to become the favoured product.&lt;/li&gt;&lt;li&gt;Microsoft: to make this kind of announcement, about a product that has been out for less than 12 months, is not a good look!  (LINQ to SQL's production release was roughtly 11 months ago).  This is particularly true in the area of data access, where there were already plenty of jokes about a long history of technical changes - &lt;a href="http://www.joelonsoftware.com/articles/fog0000000339.html"&gt;ODBC, RDO, DAO, ADO, OLEDB, now ADO.NET.&lt;/a&gt;&lt;/li&gt;&lt;li&gt;For projects you start today, with .NET 3.5, I believe the advice I gave in the presentation is still accurate.  For simple mapping consider products like LINQ to SQL and LightSpeed; for complex mapping consider products like LINQ to Entities and nHibernate.   &lt;em&gt;If&lt;/em&gt; Microsoft achieves the goals mentioned above, my advice &lt;em&gt;might&lt;/em&gt; change for &lt;em&gt;new &lt;/em&gt;projects that are started after .NET 4 is released.&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/24760385-1829171684730202341?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/1829171684730202341/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/11/future-of-linq-to-sql.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/1829171684730202341'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/1829171684730202341'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/11/future-of-linq-to-sql.html' title='Future of LINQ to SQL'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-24760385.post-3747430092097230603</id><published>2008-10-21T01:13:00.000-07:00</published><updated>2008-10-21T01:21:42.463-07:00</updated><title type='text'>Presenting at Christchurch Code Camp 2008</title><content type='html'>I'm presenting at the &lt;a href="http://dot.net.nz/Default.aspx?tabid=119"&gt;Christchurch Code Camp&lt;/a&gt; on 1 November.&lt;br /&gt;&lt;br /&gt;I'm presenting on LINQ-to-SQL and also on my open source project, &lt;a href="http://www.codeplex.com/ActiveSharp"&gt;ActiveSharp&lt;/a&gt;.  If &lt;em&gt;you &lt;/em&gt;were coming to a presentation on either of those topics, what would you like to hear?  (This is your chance to shape the presentations, because I haven't finished writing them yet ;-)&lt;br /&gt;&lt;br /&gt;At the moment, the abstracts for the two presentations look like this:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;strong&gt;Title: &lt;/strong&gt;Extending LINQ to SQL&lt;br /&gt;&lt;br /&gt;Abstract: How to build on LINQ to SQL to add extra capabilities and work around the product’s limitations.  The presentation will share techniques we’ve used at Optimation to "push the envelope" when using LINQ to SQL.  I’ll outline the base techniques, how we’ve applied them, and the minor limitations that remain unresolved. For those new to LINQ to SQL, the presentation will begin with a whirlwind introduction to the product.  It will conclude with some thoughts on how LINQ fits into the "big picture" of .NET ORM tools.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;and &lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;strong&gt;Title:&lt;/strong&gt; Low-Level .NET – a look at ActiveSharp&lt;br /&gt;&lt;br /&gt;Abstract: How to get started on working with MSIL, the low-level "assembly" language for .NET.  The presentation is based on my experiences writing ActiveSharp, a library which parses MSIL at runtime and also emits its own runtime-generated methods.  I’ll introduce the key concepts, cover some techniques to help you "cheat" while you learn, and include examples from the ActiveSharp codebase.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;What do you think?  Am I focusing on the right points?  Are there other aspects of these subjects which you'd prefer me to cover instead?  All suggestions welcome...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/24760385-3747430092097230603?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/3747430092097230603/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/10/presenting-at-christchurch-code-camp.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/3747430092097230603'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/3747430092097230603'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/10/presenting-at-christchurch-code-camp.html' title='Presenting at Christchurch Code Camp 2008'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-24760385.post-3039149428774094370</id><published>2008-10-04T15:44:00.000-07:00</published><updated>2008-10-04T16:17:51.203-07:00</updated><title type='text'>How eBoostr Works</title><content type='html'>I'm &lt;a href="http://dotnet.agilekiwi.com/blog/2008/09/visual-studio-performance-with-slow.html"&gt;using eBoostr&lt;/a&gt; to speed up compile times in Visual Studio.&lt;br /&gt;&lt;br /&gt;My only complaint with the product was the lack of documentation on what it caches and when. You can view the list of all the files that it is caching, but I couldn't find any documentation on how it actually chooses which files to cache. So, I emailed eBoostr technical support, and they sent back a very helpful and informative reply - which they kindly allowed me to quote in this post.&lt;br /&gt;&lt;br /&gt;eBoostr works as follows:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;It monitors all read/write requests to the hard disk, and gathers statistics on the most frequently-read files&lt;/li&gt;&lt;li&gt;By default it will "update cache contents each hour during computer idle time automatically". You can also manually request a cache rebuild (if your computer has no idle time(!), or you just want the cache to reflect your most recent usage patterns).&lt;/li&gt;&lt;li&gt;It doesn't mess with write operations. Each write goes straight to the real disk. If the file was cached, the cached copy is invalidated. The cached copy will not become valid again until the next cache rebuild.&lt;/li&gt;&lt;li&gt;If you are using both RAM and USB caching, RAM "has the highest priority" (so gets the most frequently used files, I presume). Files in RAM are not cached on USB.&lt;/li&gt;&lt;/ol&gt;At first, the algorithm struck me as a little crude. But on reflection I realised that it makes sense. By rebuilding the cache in batch mode (either automatically or manually) eBooster can make sure that the cache reflects the most commonly-used files. Contrast that with the other approach, which would be to move a file into the cache as soon as it is read - possibly meaning that an infrequently-read file, which maybe you are only going to read once, will bump a more frequently-used file out of the cache.&lt;br /&gt;&lt;br /&gt;Subjectively, eBoostr seems to be working well for me. And as I've &lt;a href="http://dotnet.agilekiwi.com/blog/2008/09/visual-studio-performance-with-slow.html"&gt;mentioned previously&lt;/a&gt;, it seems to be getting very high cache hit ratios in my typical daily usage.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/24760385-3039149428774094370?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/3039149428774094370/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/10/how-eboostr-works.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/3039149428774094370'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/3039149428774094370'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/10/how-eboostr-works.html' title='How eBoostr Works'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-24760385.post-8699053366690186926</id><published>2008-09-15T01:15:00.000-07:00</published><updated>2008-10-04T16:15:01.769-07:00</updated><title type='text'>Visual Studio Performance with Slow Laptop Drives</title><content type='html'>As &lt;a href="http://weblogs.asp.net/scottgu/archive/2007/11/01/tip-trick-hard-drive-speed-and-visual-studio-performance.aspx"&gt;Scott Guthrie wrote&lt;/a&gt;, hard drive speed makes a big difference to the performance of Visual Studio.&lt;br /&gt;&lt;br /&gt;So what can you do if, like me, you are using a laptop and so can't upgrade to a faster hard-drive? I've found two things that have helped a &lt;span style="FONT-STYLE: italic"&gt;lot&lt;/span&gt;. In one test case they reduced my build time from 28 seconds down to 3 seconds(*).&lt;br /&gt;&lt;br /&gt;&lt;span style="FONT-WEIGHT: bold"&gt;Step 1: Avoid slow virus scanners&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This made the biggest difference of all. As &lt;a href="http://www.codinghorror.com/blog/archives/000803.html"&gt;Jeff Atwood reports&lt;/a&gt;, some real-time anti-virus scanners can slow your machine down drastically. My test build dropped from 28 seconds to 7 seconds when I turned off my virus scanner! That seems entirely consistent with the results that Jeff has summarised on his page. In fact, judging by his post, it appears that some products may be even worse.&lt;br /&gt;&lt;br /&gt;For the record, I was using TrendMicro OfficeScan. I don't know why it had such a large adverse impact. Googling the vendor's website failed to unearth anything relevant, but I've heard anecdotal evidence of it reading all bytes in a file when Visual Studio merely wants to check the timestamp. On the other hand, my colleague on the next desk uses the same product (on faster disk hardware) and says it's OK.&lt;br /&gt;&lt;br /&gt;[Update: I've switched to AVG and it's looking good - much, much faster.  I'm also trialing NOD32 on another machine, because I've read good things about it.]&lt;br /&gt;&lt;br /&gt;&lt;span style="FONT-WEIGHT: bold"&gt;Step 2: Use disk caching (with lots of RAM)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I've upgraded to a total of 4GB RAM in my laptop. Since I'm running Windows XP, the operating system only sees &lt;a href="http://members.cox.net/slatteryt/RAM.html"&gt;3-and-a-bit&lt;/a&gt;, but that still gives me enough to run an in-memory disk cache.&lt;br /&gt;&lt;br /&gt;I'm using &lt;a href="http://www.eboostr.com/"&gt;eBoostr&lt;/a&gt; to run the cache. It seems to be working very well. It reduced my test build from 7 seconds down to 3 seconds, and subjectively it seems to be having a noticable positive influence*.&lt;br /&gt;&lt;br /&gt;If you go to the eBoostr site, you'll see that it is advertised as being the XP equivalent of two Vista technologies, ReadyBoost and SuperFetch. Those technologies are about reducing system boot and application start times, but it also turns out to be good at reducing &lt;span style="FONT-STYLE: italic"&gt;compilation&lt;/span&gt; times. That's not suprising really, since it works by caching the files that are most frequently used. Since I'm interested in compile times rather than boot times, I have configured it to do all it's caching in RAM. I don't even plug in a USB device.&lt;br /&gt;&lt;br /&gt;In a typical day's coding its built-in monitoring tool reports average cache hit ratios of around 80 or 90%, which means it's allowing the machine to skip a &lt;span style="FONT-STYLE: italic"&gt;lot&lt;/span&gt; of disk access.&lt;br /&gt;&lt;br /&gt;I definetely recommend giving eBoostr a try. The cost is very competitive and it has very generous evaluation terms - you can use the eval copy for ever, with the only limitation being that it turns itself off 4 hours after every reboot. This means you can take your time evaluating it, as long as you don't mind rebooting daily.&lt;br /&gt;&lt;br /&gt;My only criticism would be that the documentation doesn't really explain how it decides which files to cache. I emailed the vendor about that point, and they sent a very informative reply, which I'll summarise in a future post [&lt;a href="http://dotnet.agilekiwi.com/blog/2008/10/how-eboostr-works.html"&gt;here&lt;/a&gt;].&lt;br /&gt;&lt;br /&gt;One word of advice: if you run Visual Studio and a local copy of SQL Server (as I do), don't bother with RAM caching if you only have 2GB of RAM. Get more RAM first, then start caching. I'm using a cache size of about 800MB, which seems large enough to be useful, and small enough to leave enough RAM for all my dev tools.&lt;br /&gt;&lt;br /&gt;&lt;span style="FONT-WEIGHT: bold"&gt;Finally...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;(*) Your mileage may vary - and in fact my mileage does too, depending on what I'm doing and (presumably) on what is in the cache at the time. In some of my tests, the virus scanner seems to account for all the difference; with little difference coming from the cache. In other tests, the cache makes a noticable difference.&lt;br /&gt;&lt;br /&gt;In any case, I'm enjoying TDD again. The 30-second builds used to break my chain of thought, but now the edit-compile-test cycle is short enough that it doesn't interrupt my &lt;a href="http://en.wikipedia.org/wiki/Flow_(psychology)"&gt;flow&lt;/a&gt;. All in all, my 5400 RPM drive no longer feels like a serious problem.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/24760385-8699053366690186926?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/8699053366690186926/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/09/visual-studio-performance-with-slow.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/8699053366690186926'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/8699053366690186926'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/09/visual-studio-performance-with-slow.html' title='Visual Studio Performance with Slow Laptop Drives'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-24760385.post-4242940424578390389</id><published>2008-08-30T14:01:00.000-07:00</published><updated>2008-09-09T02:32:10.940-07:00</updated><title type='text'>Syntactic Noise sample in C#</title><content type='html'>Martin Fowler wrote an interesting post on &lt;a href="http://martinfowler.com/bliki/SyntacticNoise.html"&gt;syntactic noise in internal DSLs&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I thought it would be interesting to compare the Java versions (there are two in his post) with a concise C# version. Here is the result, the most concise C# version that I could come up with:&lt;br /&gt;&lt;p&gt;&lt;span style="color:#ff0000;"&gt;static&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Event&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DoorClosed &lt;span style="color:#ff0000;"&gt;= "&lt;/span&gt;D1CL&lt;span style="color:#ff0000;"&gt;",&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DrawOpened &lt;span style="color:#ff0000;"&gt;= "&lt;/span&gt;D2OP&lt;span style="color:#ff0000;"&gt;", &lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LightOn &lt;span style="color:#ff0000;"&gt;= "&lt;/span&gt;L1ON&lt;span style="color:#ff0000;"&gt;";&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#ff0000;"&gt;static  Command&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LockPanel &lt;span style="color:#ff0000;"&gt;= "&lt;/span&gt;PNLK&lt;span style="color:#ff0000;"&gt;",&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;UnlockDoor &lt;span style="color:#ff0000;"&gt;= "&lt;/span&gt;D1UL&lt;span style="color:#ff0000;"&gt;";&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#ff0000;"&gt;static&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;State&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Idle &lt;span style="color:#ff0000;"&gt;= new State&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;UnlockDoor&lt;span style="color:#ff0000;"&gt;, &lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LockPanel&lt;span style="color:#ff0000;"&gt;,&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DoorClosed&lt;span style="color:#ff0000;"&gt;.TransitionTo(&lt;/span&gt;Active&lt;span style="color:#ff0000;"&gt;)&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#ff0000;"&gt;},&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Active &lt;span style="color:#ff0000;"&gt;= new State&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#ff0000;"&gt;{&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DrawOpened&lt;span style="color:#ff0000;"&gt;.TransitionTo(&lt;/span&gt;WaitingForLight&lt;span style="color:#ff0000;"&gt;),&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LightOn&lt;span style="color:#ff0000;"&gt;.TransitionTo(&lt;/span&gt;WaitingForDraw&lt;span style="color:#ff0000;"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It's reasonably concise (slightly more so that the fluent Java one I think), however it did require me to make everything static - which kind of counts as cheating ;-) &lt;strong&gt;[Update 9 Sept:]&lt;/strong&gt; So here is a more realistic version:&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="color:#ff0000;"&gt;public Event&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;DoorClosed &lt;span style="color:#ff0000;"&gt;= "&lt;/span&gt;D1CL&lt;span style="color:#ff0000;"&gt;",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;DrawOpened &lt;span style="color:#ff0000;"&gt;= "&lt;/span&gt;D2OP&lt;span style="color:#ff0000;"&gt;",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;LightOn &lt;span style="color:#ff0000;"&gt;= "&lt;/span&gt;L1ON&lt;span style="color:#ff0000;"&gt;";&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#ff0000;"&gt;public Command&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;LockPanel &lt;span style="color:#ff0000;"&gt;= "&lt;/span&gt;PNLK&lt;span style="color:#ff0000;"&gt;",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;UnlockDoor &lt;span style="color:#ff0000;"&gt;= "&lt;/span&gt;D1UL&lt;span style="color:#ff0000;"&gt;";&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#ff0000;"&gt;public State&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Idle&lt;span style="color:#ff0000;"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Active&lt;span style="color:#ff0000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#ff0000;"&gt;protected void Setup()&lt;br /&gt;{&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#ff0000;"&gt;Idle &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;= new State&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;UnlockDoor,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LockPanel,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DoorClosed&lt;span style="color:#ff0000;"&gt;.TransitionTo(&lt;/span&gt;Active&lt;span style="color:#ff0000;"&gt;)&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#ff0000;"&gt;};&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#ff0000;"&gt;Active &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;= new State&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DrawOpened&lt;span style="color:#ff0000;"&gt;.TransitionTo(&lt;/span&gt;WaitingForLight&lt;span style="color:#ff0000;"&gt;), &lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LightOn&lt;span style="color:#ff0000;"&gt;.TransitionTo(&lt;/span&gt;WaitingForDraw&lt;span style="color:#ff0000;"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#ff0000;"&gt;};&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The key differences from the Java version are that it uses implicit conversions to convert strings directly to Events and Commands, and that it uses collection initializers to set up the contents of the States. (Note that a collection initializer need not contain things that are all of the same type. Instead, it will accept all types for which the target collection has an Add method. In our case, that is Commands and Transitions (created by TransitionTo)).&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Full &lt;a href="http://www.agilekiwi.com/dotnet/SyntacticNoiseCSharpSample.cs"&gt;source code&lt;/a&gt; is attached.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;PS as I've noted &lt;a href="http://dotnet.agilekiwi.com/blog/2006/10/shorthand-interfaces.html"&gt;before&lt;/a&gt;, I think that C# offers more options for in-language DSL syntax than Java.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/24760385-4242940424578390389?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/4242940424578390389/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/08/syntactic-noise-sample-in-c.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/4242940424578390389'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/4242940424578390389'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/08/syntactic-noise-sample-in-c.html' title='Syntactic Noise sample in C#'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-24760385.post-8783795275666879832</id><published>2008-08-26T01:14:00.002-07:00</published><updated>2008-10-10T01:57:04.286-07:00</updated><title type='text'>A Practical Step in the Stored Proc Debate</title><content type='html'>I've taken a practical step in the long-running debate for and against stored procs.&lt;br /&gt;&lt;br /&gt;I've logged a &lt;a href="https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=357997"&gt;formal suggestion&lt;/a&gt; with Microsoft asking them to correct their erroneous advice on the subject. :-)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms978510.aspx"&gt;This&lt;/a&gt; Patterns and Practices page says:&lt;br /&gt;&lt;blockquote&gt;Stored procedures generally result in improved performance because the database can optimize the data access plan used by the procedure and cache it for subsequent reuse.&lt;/blockquote&gt;&lt;br /&gt;That's been factually incorrect for the last decade! In terms of query plan caching, Parameterized SQL and Stored Procs are &lt;a href="http://weblogs.asp.net/fbouma/archive/2003/11/18/38178.aspx"&gt;handled in the same way&lt;/a&gt; - and they have been since SQL Server 7. &lt;br /&gt;&lt;br /&gt;So, if you too are disappointed by the level of erroneous information in this &lt;a href="http://weblogs.asp.net/fbouma/archive/2006/05/26/Yay_2100_-A-new-Stored-Proc-vs.-Dyn.-Sql-battle_2100_.aspx"&gt;long running&lt;/a&gt; debate, head over to the &lt;a href="https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=357997"&gt;feedback page&lt;/a&gt; and support my request to fix the P&amp;amp;P page. You can support it via commenting on the page or by using the Validation link at the top. &lt;br /&gt;&lt;br /&gt;Let's hope we can get the page corrected, and achieve a small step for rationality in an often irrational debate :-)&lt;br /&gt;&lt;br /&gt;(Apologies to Microsoft if my tone sounds hash. I know you've already got the correct information up on other parts of your site.)&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Update Oct 08:&lt;/strong&gt; the P&amp;P guidance &lt;a href="http://blogs.msdn.com/jmeier/archive/2008/09/02/patterns-practices-app-arch-guide-2-0-project.aspx"&gt;is being updated&lt;/a&gt;, so one presumes this will be fixed as part of that work.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/24760385-8783795275666879832?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/8783795275666879832/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/08/practical-step-in-stored-proc-debate.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/8783795275666879832'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/8783795275666879832'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/08/practical-step-in-stored-proc-debate.html' title='A Practical Step in the Stored Proc Debate'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-24760385.post-4621056278700105749</id><published>2008-07-18T02:11:00.000-07:00</published><updated>2008-07-18T03:03:35.765-07:00</updated><title type='text'>Software Development Meme</title><content type='html'>I've been tagged by &lt;a href="http://andrewpeters.net/2008/07/11/when-memes-attack/"&gt;Andrew&lt;/a&gt;, in a software development &lt;a href="http://thedailymeme.com/what-is-a-meme/"&gt;meme&lt;/a&gt; that started way back &lt;a href="http://www.michaeleatonconsulting.com/blog/archive/2008/06/04/how-did-you-get-started-in-software-development.aspx"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;How old were you when you started programming?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I was exactly 13.  My parents bought me my first computer for my 13th birthday.  It was a second-hand &lt;a href="http://www.technology.niagarac.on.ca/staff/mcsele/OhioScientific.html"&gt;Ohio Scientific Superboard II&lt;/a&gt;.  &lt;br /&gt;&lt;br /&gt;By the way, the Superboard shipped in 1978 as a single circuit board.  It had keys mounted on the front and chips mounted on the back.  That’s it.  No case, no nothing – just one big circuit board with stuff on it.  By the time it reached me a few years later, mine had been fitted into a hand-built wooden case, and its memory had been expanded to 16&lt;span style="font-style:italic;"&gt;k&lt;/span&gt;.  (I still have the machine.  If anyone knows how to fix a Superboard II that won’t respond to the Break key after power-up, please &lt;a href="http://www.agilekiwi.com/contact.htm"&gt;contact me&lt;/a&gt; :-)  &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;How did you get started in programming?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Before my SuperBoard, I’d only seen two other computers.  I guess they must have made a big impression on me.  I got Mum and Dad to buy me a book on programming in BASIC, and the purchase of the actual computer followed sometime after.  I don’t recall how much nagging was involved ;-)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;What was your first language?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The Superboard’s version of BASIC, which was &lt;a href="http://blogs.sun.com/Drew/entry/has_anyone_else_heard_of"&gt;apparently&lt;/a&gt; "Microsoft 6502 BASIC version 1.0 revision 3.2".  In hindsight, I love the fact that it was simple enough for a 13 year-old to learn the whole language.  If I recall correctly, there was IF .. THEN, but no ELSE; and GOTO but no GOSUB.  Definitely a minimal language.  It made me appreciate "real" languages when I finally got to use them.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;What was the first real program you wrote?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It was a clone of the first computer program I’d ever seen – a game where you had to steer a tank through a minefield.  My version had the randomly-generated minefield, and the tank that was stuck on full-throttle while you steered your way though, but it lacked the system-generated comments that poked fun at your crashes.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;What languages have you used since you started programming?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I’ve done serious development in Pascal, Excel 4.0 Macro language, VBA, Ada, PowerBuilder, PL-SQL, Delphi and C#.  I’ve dabbled in various others including C++, JavaScript and even VB.NET (although it makes my eyes hurt when I read it ;-)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;What was your first professional programming gig?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I did a few small jobs in BASIC and Excel when I was a student, but my first really serious job was in PowerBuilder for an IT consultancy.  PowerBuilder’s (in)famous DataWindow really was a fast way to get things done.  It set the bar for productivity, and it's only now in 2008 that I feel like we've replicated that speed in .NET - thanks to a good ORM and our in-house framework. (And we get a proper domain model with layering, which we never had in PB!)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;If you knew then what you know now, would you have started programming?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Yes.  &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;If there is one thing you learned along the way that you would tell new developers, what would it be?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I might tell them that it’s not about technology, it’s really about people – but I don’t think they’d believe me.  &lt;br /&gt;&lt;br /&gt;So instead I’d tell them to read &lt;a href="http://samizdat.mines.edu/howto/HowToBeAProgrammer.html"&gt;How to be a Programmer&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;What’s the most fun you’ve ever had... programming?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I’ve particularly enjoyed my old Superboard; writing (most of) a compiler at university; doing some funky stuff with COM in Delphi; and releasing &lt;a href="http://www.codeplex.com/ActiveSharp"&gt;a&lt;/a&gt; &lt;a href="http://www.codeplex.com/Close2Poco"&gt;couple&lt;/a&gt; of open source projects.  &lt;br /&gt;&lt;br /&gt;But the thing I look back on most fondly is a .NET project at &lt;a href="http://www.optimation.co.nz"&gt;Optimation&lt;/a&gt;.  The highlight wasn’t the technology, which was interesting but not amazing; the highlight was the project as a whole.  We had great collaboration with the customer, very much "one team" with great dialogue and innovation, and together we exceeded expectations instead of merely meeting requirements.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Over to you&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.nichesoftware.co.nz/"&gt;Bevan&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.smartbeanz.net/blog/"&gt;Eduard&lt;/a&gt;&lt;br /&gt;and&lt;br /&gt;&lt;a href="http://blogs.msdn.com/kirillosenkov/"&gt;Kirill&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/24760385-4621056278700105749?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/4621056278700105749/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/07/software-development-meme.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/4621056278700105749'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/4621056278700105749'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/07/software-development-meme.html' title='Software Development Meme'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-24760385.post-817866053730141821</id><published>2008-07-15T03:08:00.000-07:00</published><updated>2008-07-15T03:13:56.166-07:00</updated><title type='text'>POCO LINQ Update</title><content type='html'>&lt;a href="http://www.codeplex.com/Close2Poco"&gt;Here &lt;/a&gt;is my &lt;a href="http://dotnet.agilekiwi.com/blog/2007/12/interested-in-poco-linq.html"&gt;long-promised&lt;/a&gt; near-POCO solution for LINQ to SQL.&lt;br /&gt;&lt;br /&gt;As planned, it is deliberately not 100% pure POCO, but it does implement these key goals:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Entity classes are simple enough to be hand-written (no need to generate them with SQL Metal or VS 2008)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Mapping is easy (no need to manually map every property via attributes or external XML)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Lazy-loading works&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Bi-directional relationships work (update one end, and the other is synchronized automatically)&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/24760385-817866053730141821?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/817866053730141821/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/07/poco-linq-update.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/817866053730141821'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/817866053730141821'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/07/poco-linq-update.html' title='POCO LINQ Update'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-24760385.post-2258890035993646136</id><published>2008-06-07T14:20:00.000-07:00</published><updated>2008-06-07T14:40:55.449-07:00</updated><title type='text'>Another reason why architects should write code</title><content type='html'>Johanna Rothman explains why &lt;a href="http://www.jrothman.com/weblog/2006/04/architects-must-write-code.html"&gt;architects should write code&lt;/a&gt;.  I completely agree.  &lt;br /&gt;&lt;br /&gt;Not only does hands-on involvement reduce risks on the project, it also reduces embarassment when talking to your kids ;-)  Here's an actual conversation with my daughter:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;What did you do today Dad?&lt;/span&gt;&lt;br /&gt;I drew some diagrams.  Do you know what a diagram is?&lt;br /&gt;&lt;span style="font-style:italic;"&gt;No&lt;/span&gt;&lt;br /&gt;It's a picture that shows how something works.  I drew some diagrams, then I talked with some people about them.&lt;br /&gt;&lt;span style="font-style:italic;"&gt;So you didn't do any work then?&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/24760385-2258890035993646136?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/2258890035993646136/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/06/another-reason-why-architects-should.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/2258890035993646136'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/2258890035993646136'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/06/another-reason-why-architects-should.html' title='Another reason why architects should write code'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-24760385.post-736508247811786036</id><published>2008-04-30T01:51:00.000-07:00</published><updated>2008-04-30T02:26:30.744-07:00</updated><title type='text'>Only 4 New Features in C# vNext?</title><content type='html'>I've always admired the effort that Microsoft put into the design of C#.  It's  difficult to find the right balance between power and flexibility, and on the whole I think they've done an excellent job.&lt;br /&gt;&lt;br /&gt;At the same time, it's been great to see the language grow, particularly with the addition of LINQ.  As Jon Skeet has written recently, C# today is noticably more complicated than it was at version 1.0.  Personally, I don't think that's a bad thing. The C# community has grown up along with the langauage, learning the new features as they have been released.&lt;br /&gt;&lt;br /&gt;I can see this process continuing for some time, with the language continuing to grow.  So I was suprised to see this comment from Microsoft's Mads Torgersen, in response to &lt;a href="https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=233329"&gt;some&lt;/a&gt; &lt;a href="https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=278510"&gt;suggestions&lt;/a&gt; that I posted at &lt;a href="http://connect.microsoft.com"&gt;Microsoft Connect&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;"We have to do some harsh prioritization, both because of our implementation and testing resources, but also because we need to keep the number of new langauge features at a manageable level - depending on how you count, &lt;span style="font-weight:bold;"&gt;we are adding only four language features to C# this time around&lt;/span&gt;".&lt;/blockquote&gt;We more-or-less know that one will be some form of &lt;a href="http://blogs.msdn.com/charlie/archive/2008/01/25/future-focus.aspx"&gt;dynamic lookup&lt;/a&gt;. That just leaves three others.  They might be big "killer" features (like generics and lambda expressions in previous versions) but there's still only &lt;span style="font-style:italic;"&gt;three&lt;/span&gt; of them.&lt;br /&gt;&lt;br /&gt;I don't know what to think. Should we be trilled that Microsoft are continuing their excellent track record of keeping the language simple, or should we be dissapointed that there will be so few improvements?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/24760385-736508247811786036?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/736508247811786036/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/04/only-4-new-features-in-c-vnext.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/736508247811786036'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/736508247811786036'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/04/only-4-new-features-in-c-vnext.html' title='Only 4 New Features in C# vNext?'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-24760385.post-1766524731146027945</id><published>2008-02-23T21:30:00.001-08:00</published><updated>2008-04-11T15:00:07.629-07:00</updated><title type='text'>Summary of C# vNext Ideas in this Blog</title><content type='html'>Here's a summary of the ideas I've suggested in this blog, for future versions of C#:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://dotnet.agilekiwi.com/blog/2007/11/making-extension-methods-safer.html"&gt;Fix the versioning issues&lt;/a&gt; with extension methods&lt;/li&gt;&lt;li&gt;Consider "&lt;a href="http://kirillosenkov.blogspot.com/2007/11/john-rusk-on-extension-interfaces.html"&gt;extension interfaces&lt;/a&gt;" to provide mixin-like behaviour&lt;/li&gt;&lt;li&gt;Also, consider improving the &lt;a href="http://dotnet.agilekiwi.com/blog/2008/01/resolving-extension-methods.html"&gt;resolving&lt;/a&gt; of extension methods&lt;/li&gt;&lt;li&gt;Retain some means of serializing iterator state (even if the underlying iterator implementation is changed) (See comments &lt;a href="http://dotnet.agilekiwi.com/blog/2007/05/implementing-workflow-with-persistent.html"&gt;here&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;Provide an &lt;a href="http://dotnet.agilekiwi.com/blog/2006/06/direct-support-for-symbol-names.html"&gt;infoof operator&lt;/a&gt;, or similar&lt;/li&gt;&lt;li&gt;&lt;a href="http://dotnet.agilekiwi.com/blog/2007/04/quoted-strings.html"&gt;Better handling of @-quoted strings&lt;/a&gt; that contain double quotes&lt;li&gt;&lt;a href="http://dotnet.agilekiwi.com/blog/2008/02/enhanced-automatic-properties.html"&gt;Enhance automatic properties&lt;/a&gt; to retain their concise syntax but to offer greater flexibility to use programmer-defined code. Particularly helpful for &lt;a href="http://dotnet.agilekiwi.com/blog/2008/02/better-property-change-notification.html"&gt;automatic INotifyPropertyChanged implementation&lt;/a&gt;&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/24760385-1766524731146027945?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/1766524731146027945/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/02/summary-of-c-vnext-ideas-in-this-blog.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/1766524731146027945'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/1766524731146027945'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/02/summary-of-c-vnext-ideas-in-this-blog.html' title='Summary of C# vNext Ideas in this Blog'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-24760385.post-7489636117821045320</id><published>2008-02-23T20:41:00.000-08:00</published><updated>2008-03-12T01:04:49.755-07:00</updated><title type='text'>Enhanced Automatic Properties</title><content type='html'>Recently there's been a lot of blog posts discussing things people would like to see in the next version of C#.  Here's my addition to the wish-list:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;"Automatic properties that let me supply a method body."&lt;/i&gt;  It sounds like a contradiction in terms - but it doesn't have to be.  Instead, it would be a compact syntax for defining properties that use standardised method bodies (where &lt;span style="font-style:italic;"&gt;you&lt;/span&gt; define your own "standard" bodies).&lt;br /&gt;&lt;br /&gt;Some places where it would be useful:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Cases where  many properties follow a standard format.  For instance, all the properties generated by the LINQ designer could be single-line automatic properties.  (Much less verbose than the current approach).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;ORM's and similar products that require properties to be written according to certain conventions.  (E.g. &lt;a href="http://www.mindscape.co.nz/products/LightSpeed/"&gt;Mindscape LightSpeed&lt;/a&gt;)&lt;/li&gt;&lt;/ol&gt;&lt;strong&gt;How would it look?&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Right now, we can write automatic properties like this:&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; Foo { get; set; }&lt;/pre&gt;My suggestion is that the words "get" and "set" could be replaced by the names of methods.  For instance:&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; AdvancedFoo { GetValue; SetValue; }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Where the methods "GetValue" and "SetValue" are generic instance methods with these signatures:&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;/// When passed the field, return the property value&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;T GetValue&amp;lt;T&amp;gt;(&lt;span class="kwrd"&gt;ref&lt;/span&gt; T field)&lt;br /&gt;{&lt;br /&gt;    &lt;span class="rem"&gt;// ... your own code goes here...&lt;/span&gt;&lt;br /&gt;}&lt;br /&gt;       &lt;br /&gt;&lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;/// When passed the field, by ref, and the new property value, set the field&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;void&lt;/span&gt; SetValue&amp;lt;T&amp;gt;(&lt;span class="kwrd"&gt;ref&lt;/span&gt; T field, T &lt;span class="kwrd"&gt;value&lt;/span&gt;)&lt;br /&gt;{&lt;br /&gt;    &lt;span class="rem"&gt;//...your own code goes here...&lt;/span&gt;&lt;br /&gt;}&lt;/pre&gt;  Given the above property, "AdvancedFoo", the compiler would compile it as if I had written this:&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; AdvancedFoo&lt;br /&gt;{&lt;br /&gt;    get { &lt;span class="kwrd"&gt;return&lt;/span&gt; GetValue(&lt;span class="kwrd"&gt;ref&lt;/span&gt; _advancedFoo); }&lt;br /&gt;    set { SetValue( &lt;span class="kwrd"&gt;ref&lt;/span&gt; _advancedFoo, &lt;span class="kwrd"&gt;value&lt;/span&gt;); }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; _advancedFoo; &lt;span class="rem"&gt;// compiler-generated backing field&lt;/span&gt;&lt;/pre&gt; Just as in today's automatic properties, the compiler would generate the backing field for me.  The difference is that it reads and writes that backing field via methods which I define.&lt;br /&gt;&lt;br /&gt;This goes a long way towards giving the best of both worlds: the compact syntax of automatic properties, and the flexibility of my own code (plus standardisation - all me properties that are supposed to work the same way &lt;span style="font-style:italic;"&gt;do&lt;/span&gt; work the same way, because they all use the same code).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Questions:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Why does the "GetValue" method take the field "by ref"?&lt;/span&gt;  SetValue needs it by ref, but why GetValue?  GetValue takes it by ref simply so that you can use &lt;a href="http://dotnet.agilekiwi.com/blog/2008/02/better-property-change-notification.html"&gt;this trick&lt;/a&gt; to find out &lt;span style="font-style:italic;"&gt;which&lt;/span&gt; property is being read - just in case you need to know.  This is something you are more likely to need to know when setting, e.g. to raise change notificiations, but maybe some people want to identify the property in GetValue too.  Using the ref param makes that possible.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;What type should the complier use for the backing field?&lt;/span&gt;  Simply put, it should use whatever field type is implied by the field parameters of the "GetValue" and "SetValue" methods.  E.g. an automatic property for a LINQ EntityRef might look like this:&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;T GetEntity(&lt;span class="kwrd"&gt;ref&lt;/span&gt; EntityRef&amp;lt;T&amp;gt; field) &lt;span class="kwrd"&gt;where&lt;/span&gt; T:&lt;span class="kwrd"&gt;class&lt;/span&gt;&lt;br /&gt;{}&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;void&lt;/span&gt; SetEntity(&lt;span class="kwrd"&gt;ref&lt;/span&gt; EntityRef&amp;lt;T&amp;gt; field, T &lt;span class="kwrd"&gt;value&lt;/span&gt;) &lt;span class="kwrd"&gt;where&lt;/span&gt; T:&lt;span class="kwrd"&gt;class&lt;/span&gt;&lt;br /&gt;{}&lt;br /&gt;&lt;/pre&gt; allowing me to write this:&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; Customer Bar{ GetEntity; SetEntity; }&lt;br /&gt;&lt;/pre&gt; and have the compiler compile it as if I had written this:&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; Customer Bar&lt;br /&gt;{&lt;br /&gt;    get { &lt;span class="kwrd"&gt;return&lt;/span&gt; GetEntity(&lt;span class="kwrd"&gt;ref&lt;/span&gt; _bar);}&lt;br /&gt;    set { SetEntity(&lt;span class="kwrd"&gt;ref&lt;/span&gt; _bar, &lt;span class="kwrd"&gt;value&lt;/span&gt;);}&lt;br /&gt;}&lt;br /&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; EntitySet&amp;lt;Customer&amp;gt; _bar;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Note that the compiler is able to infer that the backing field should be EntitySet&lt;Customer&gt;, not Customer, based on the signatures of Get/SetEntity.&lt;br /&gt;&lt;br /&gt;&lt;small&gt;(And how would Get/SetEntity actually work?  That's a question for another day ;-)  I do have some (working) prototype code...)&lt;/small&gt;&lt;br /&gt;&lt;br /&gt;What do you think of this idea for enhanced automatic properties?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Update 2 March:&lt;/span&gt; posted on MS Connect &lt;a href="https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=278125"&gt;here&lt;/a&gt; (in the comments)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Update 12 March:&lt;/span&gt; And here &lt;a href="http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=332659"&gt;here&lt;/a&gt; as an MS Connect item in its own right.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/24760385-7489636117821045320?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/7489636117821045320/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/02/enhanced-automatic-properties.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/7489636117821045320'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/7489636117821045320'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/02/enhanced-automatic-properties.html' title='Enhanced Automatic Properties'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-24760385.post-4950512805883917891</id><published>2008-02-14T00:43:00.000-08:00</published><updated>2008-02-14T00:46:39.167-08:00</updated><title type='text'>Extension Methods - Feedback to Microsoft</title><content type='html'>If you've been following the disussions about &lt;a href="http://dotnet.agilekiwi.com/blog/2007/11/making-extension-methods-safer.html"&gt;extension methods&lt;/a&gt; in this blog, you might be interested to know that I've submitted the issue to Microsoft's feedback site.  &lt;a href="https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=328527"&gt;Jump over there&lt;/a&gt; and vote for it, if you'd like to see something done.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/24760385-4950512805883917891?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/4950512805883917891/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/02/extension-methods-feedback-to-microsoft.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/4950512805883917891'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/4950512805883917891'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/02/extension-methods-feedback-to-microsoft.html' title='Extension Methods - Feedback to Microsoft'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-24760385.post-4877283526663654030</id><published>2008-02-08T14:58:00.000-08:00</published><updated>2008-04-11T14:55:10.696-07:00</updated><title type='text'>Better Property Change Notification</title><content type='html'>&lt;span style="font-weight:bold;"&gt;aka Automatic INotifyPropertyChanged&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Some time ago I developed a new way to do property change notification.  It consists of code which can automatically figure out which property has changed, without you having to tell it.&lt;br /&gt;&lt;br /&gt;Details are &lt;a href="http://dotnet.agilekiwi.com/blog/2007/07/claytons-interception.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I've now put together an updated version, and posted it on CodePlex &lt;a href="http://www.codeplex.com/ActiveSharp"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Here's how to use the new version:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Option 1:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Here's the easiest option...&lt;br /&gt;&lt;br /&gt;Add this code to your class or base class:&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;PropertyChangeHelper _propertyChangeHelper = &lt;span class="kwrd"&gt;new&lt;/span&gt; PropertyChangeHelper();&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;event&lt;/span&gt; PropertyChangedEventHandler PropertyChanged&lt;br /&gt;{&lt;br /&gt;    add { _propertyChangeHelper.Add(&lt;span class="kwrd"&gt;value&lt;/span&gt;); }&lt;br /&gt;    remove { _propertyChangeHelper.Remove(&lt;span class="kwrd"&gt;value&lt;/span&gt;); }&lt;br /&gt;}&lt;br /&gt;            &lt;br /&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; SetValue&amp;lt;T&amp;gt;(&lt;span class="kwrd"&gt;ref&lt;/span&gt; T field, T &lt;span class="kwrd"&gt;value&lt;/span&gt;)&lt;br /&gt;{&lt;br /&gt;    _propertyChangeHelper.SetValue&lt;br /&gt;                          (&lt;span class="kwrd"&gt;this&lt;/span&gt;, &lt;span class="kwrd"&gt;ref&lt;/span&gt; field, &lt;span class="kwrd"&gt;value&lt;/span&gt;);&lt;br /&gt;}&lt;/pre&gt;Then write your property setter methods like this:&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; Foo&lt;br /&gt;{&lt;br /&gt;    get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _foo; }&lt;br /&gt;    set { SetValue(&lt;span class="kwrd"&gt;ref&lt;/span&gt; _foo, &lt;span class="kwrd"&gt;value&lt;/span&gt;); }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Option 2:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you want more control, you can find which property changed like this (and then do whatever you like):&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; SetValue&amp;lt;T&amp;gt;(&lt;span class="kwrd"&gt;ref&lt;/span&gt; T field, T &lt;span class="kwrd"&gt;value&lt;/span&gt;)&lt;br /&gt;{&lt;br /&gt;    ...&lt;br /&gt;    field = &lt;span class="kwrd"&gt;value&lt;/span&gt;;   &lt;span class="rem"&gt;//Actually assign the new value&lt;/span&gt;&lt;br /&gt;    PropertyInfo changedProperty = PropertyMap.GetProperty(&lt;span class="kwrd"&gt;this&lt;/span&gt;, &lt;span class="kwrd"&gt;ref&lt;/span&gt; field);&lt;br /&gt;     &lt;span class="rem"&gt;// do whatever you like, now that you know which prop was changed&lt;/span&gt;&lt;br /&gt;    ...&lt;br /&gt;}&lt;/pre&gt;Key differences in the new version are:&lt;ul&gt;&lt;br /&gt;&lt;li&gt;No "trial sets".  The old version used to call all your property setters, to figure out which fields they corresponded to.  That could be annoying, because you ended up recieving calls to the set methods when your objects were not necessarily ready for them.  The new version doesn't need to do this.  Instead, it inspects the MSIL of the set methods, to figure out what it needs to know.  (The inspection is a one-off runtime operation, so it won't be a performance problem.)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Fewer contraints on how classes are coded.  The old version required that you nominated a special field as the "reference field", to which all others were compared.  The new version does not require that.  Also, the new version lets you use your own base class (with your own SetValue method, named whatever you want).  Fianlly, you can put your own code in the property setter methods (along with the call to your "SetValue" method), something which could cause problems in the old version&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Helper class for easy implemetation of property change notifications (as above)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Granualar implementation, so that you can call some of the implmentaiton classes, but still write the outer "layer" of the API yourself if you need to&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Lock-free. The new version is threadsafe without explict locks (and without and [ThreadStatic]s). &lt;span style="font-style:italic;"&gt; Update 10 Feb:&lt;/span&gt; This used to rely on a little trick with generics and static fields; but that doesn't play well with inheriance.  It now uses a class I wrote called LazyDictionary, which is basically a dictionary with double-checked locking to ensure that locks are only requested during initialization, and not during the on-going running of the application.  (Didn't want a lock request on every property set call!)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;No separate C++ assembly.  The old version used managed C++ to do stuff that C# cannot.  The new version uses reflection emit, to produce the corresponding routine on the fly, so that the separate assembly is not required.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Finally, I have resurrected the name "ActiveSharp" (which I used for a previous, &lt;a href="http://dotnet.agilekiwi.com/blog/2007/06/no-more-development-on-my-side-project.html"&gt;abandonned project&lt;/a&gt;) for this new version of the code.  I did that for two reasons, firstly the new version borrows code from the old ActiveSharp (particulaly the MSIL inspection); and secondly I liked the old name and couldn't think of a better one ;-)  Just like the previous "ActiveSharp", this new version is a product of my &lt;a href="http://en.wikipedia.org/wiki/Micro_ISV"&gt;microISV&lt;/a&gt;, Tasman Logic Ltd.  (The microISV is not exactly a money-making venture, given that its only product is open-source ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/24760385-4877283526663654030?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/4877283526663654030/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/02/better-property-change-notification.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/4877283526663654030'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/4877283526663654030'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/02/better-property-change-notification.html' title='Better Property Change Notification'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-24760385.post-3344880181427922176</id><published>2008-01-14T23:11:00.000-08:00</published><updated>2008-01-15T00:03:18.241-08:00</updated><title type='text'>Resolving Extension Methods</title><content type='html'>Paul Stovell (author of &lt;a href="http://paulstovell.net/blog/index.php/why-synclinq-should-matter-to-you/"&gt;SyncLINQ&lt;/a&gt;) has pointed out another issue with Extension Methods.  As he &lt;a href="http://www.paulstovell.net/blog/index.php/interface-methods-versus-extension-methods#comment-3403"&gt;writes&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;The problem is the methods are *resolved* at compile time.&lt;br /&gt;&lt;br /&gt;Suppose you had this:&lt;br /&gt;&lt;br /&gt;void DoStuff(this IFoo foo);&lt;br /&gt;&lt;br /&gt;class FooFactory&lt;br /&gt;IFoo Create()&lt;br /&gt;&lt;br /&gt;If your factory returns an object that provides its own instance implementation of DoStuff, it WILL NOT be invoked - the extension method will instead. This breaks many of the rules around polymorphism and good OO in general...&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;In other words, the compiler &lt;a href="http://dotnet.agilekiwi.com/blog/2006/04/extension-methods-more-than-sugar.html"&gt;favours instance methods over extension methods&lt;/a&gt;, &lt;span style="font-style:italic;"&gt;but only if it can "see" the instance method at compile time&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;The reason is simple: currently, resolving an extension method is just a compiler trick, so compile time is the only time when it CAN be done.  &lt;br /&gt;&lt;br /&gt;But Paul's comment got me thinking.  It occured to me that, if my idea about &lt;a href="http://dotnet.agilekiwi.com/blog/2006/04/extension-methods-solution.html"&gt;using interfaces&lt;/a&gt; was implemented, then it would be possible to properly solve the problem he described. It would work like this:&lt;br /&gt;&lt;br /&gt;First, to recap: &lt;a href="http://dotnet.agilekiwi.com/blog/2006/04/extension-methods-solution.html"&gt;I suggest&lt;/a&gt; that there should be a mapping between extension methods and interfaces.  Think of a set of extension methods as an "extension contract".  You can make calls on the methods in that contact either by calling intstance methods (on objects which implement the interface) or by extension methods (for objects which do not implement the interface). This is to solve the &lt;a href="http://dotnet.agilekiwi.com/blog/2006/04/extension-methods-problem.html"&gt;versioning problem&lt;/a&gt;, but it can also be used to solve the problem Paul described.&lt;br /&gt;&lt;br /&gt;How? I'll try to illustrate with an example.  Imagine that our "extension contract" is called IExtensionContract.  It contains two methods, Foo and Bar.  We can call Foo and Bar on objects which &lt;span style="font-style:italic;"&gt;don't&lt;/span&gt; support IExtensionContract, simply by calling them as extesion methods.  But, when we call Foo and Bar on objects which DO support IExtensionContract, we want to call the version that is on the object &lt;i&gt;even if we can't tell that the object supports them at compile time&lt;/i&gt;.  (That's the heart of the issue, right Paul?)&lt;br /&gt;&lt;br /&gt;That could be done if the complier worked like this:&lt;br /&gt;&lt;br /&gt;Given this code to compile&lt;br /&gt;&lt;br /&gt;ISomething s = ...&lt;br /&gt;s.Foo();&lt;br /&gt;&lt;br /&gt;The compiler should compile it as if the programmer had written&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;ISomething = ...&lt;br /&gt;IExtensionContract c = s &lt;span class="kwrd"&gt;as&lt;/span&gt; IExtensionContract;&lt;br /&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt;(c == &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;   StaticExtender.Foo(s);  &lt;span class="rem"&gt;// invoke the extension method&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;   c.Foo();                &lt;span class="rem"&gt;// invoke the instance method&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;This would be possible, if the &lt;a href="http://dotnet.agilekiwi.com/blog/2006/04/extension-methods-solution.html"&gt;interface-based versioning solution&lt;/a&gt; was adopted, because that solution introduces just enough &lt;span style="font-style:italic;"&gt;runtime&lt;/span&gt; information about the extension methods - namely the "contract" to which the methods belong.  Contrast that to the current situation, where there is &lt;span style="font-style:italic;"&gt;no&lt;/span&gt; runtime information about extension methods.&lt;br /&gt;&lt;br /&gt;Here is the user-authored (i.e. not compiler-generated) code for the example above:&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&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; StaticExtender : IExtensionContract &lt;br /&gt;    &lt;span class="rem"&gt;// "inheriting" from interface here is my suggested addition to the language&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;     &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; Foo(&lt;span class="kwrd"&gt;this&lt;/span&gt; ISomething s){...}&lt;br /&gt;&lt;br /&gt;     &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; Bar(&lt;span class="kwrd"&gt;this&lt;/span&gt; ISomething s){...}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IExtensionContract&lt;br /&gt;{&lt;br /&gt;   &lt;span class="kwrd"&gt;void&lt;/span&gt; Foo();&lt;br /&gt;   &lt;span class="kwrd"&gt;void&lt;/span&gt; Bar();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Finally, all the suggested logic I have blogged about previously still applies. The compiler still needs to decide, at compile time, whether the call is to a method in the extension contract or to a like-named (but otherwise unrelated) instance method.  All that logic still applies as I described it &lt;a href="http://dotnet.agilekiwi.com/blog/2007/11/making-extension-methods-safer.html"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/24760385-3344880181427922176?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/3344880181427922176/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/01/resolving-extension-methods.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/3344880181427922176'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/3344880181427922176'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/01/resolving-extension-methods.html' title='Resolving Extension Methods'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-24760385.post-2370804097451603149</id><published>2008-01-12T16:59:00.000-08:00</published><updated>2008-01-12T18:56:00.809-08:00</updated><title type='text'>Readability in Validation</title><content type='html'>My favourite pattern for validation code is to have one method per validation rule.  I think it makes it easier to read and manage the rules.&lt;br /&gt;&lt;br /&gt;For instance, I like to be able to write something like this:&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;[Validate]&lt;br /&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; EndDateMustBeAfterStartDate()&lt;br /&gt;{&lt;br /&gt;  &lt;span class="kwrd"&gt;return&lt;/span&gt; EndDate &amp;gt; StartDate;&lt;br /&gt;}&lt;/pre&gt;I like to refine the pattern a little, in order to: &lt;br /&gt;&lt;br /&gt;(a) Construct error messages based on the method names.  That makes the code more concise and encourages good method names.  E.g. the failure message from the rule above will be "End date must be after start date".  &lt;br /&gt;(b) Allow you to, alternatively, specify dynamically-generated failure messges from within the method body (see below)&lt;br /&gt;(c) Easily specify if the rule is not applicable in a particular situation (again see below).&lt;br /&gt;&lt;br /&gt;I've attached some &lt;a href="http://www.agilekiwi.com/dotnet/SimpleValidation.cs"&gt;sample code&lt;/a&gt; (with &lt;a href="http://www.agilekiwi.com/dotnet/SimpleValidationTests.cs"&gt;tests&lt;/a&gt;).  &lt;br /&gt;&lt;br /&gt;By the way, I &lt;a href="http://dotnet.agilekiwi.com/blog/2007/06/no-more-development-on-my-side-project.html"&gt;once&lt;/a&gt; wrote some code to fire rules automatically, whenever a property used by the rule was changed.  But that's not included here.  In this sample, you have to ask the system explictly to run the rules at a particular time. &lt;br /&gt;&lt;br /&gt;Here are some example rules, and the code to call them:&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Animal&lt;br /&gt;{&lt;br /&gt;    ...&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; AnimalName&lt;br /&gt;    {&lt;br /&gt;        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _animalName; }&lt;br /&gt;        set { _animalName = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; NumberOfLegs&lt;br /&gt;    {&lt;br /&gt;       get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _numberOfLegs; }&lt;br /&gt;       set { _numberOfLegs = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [Validate]&lt;br /&gt;    &lt;span class="kwrd"&gt;protected&lt;/span&gt; Result NumberOfLegsMustBeEven()  &lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; NumberOfLegs % 2 == 0;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [Validate]&lt;br /&gt;    &lt;span class="kwrd"&gt;protected&lt;/span&gt; Result MythicalSpeciesAreNotAllowed()&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (AnimalName == &lt;span class="str"&gt;"Unicorn"&lt;/span&gt; || AnimalName == &lt;span class="str"&gt;"Dragon"&lt;/span&gt;)&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; Validation.Error(&lt;span class="str"&gt;"'"&lt;/span&gt; + AnimalName + &lt;span class="str"&gt;"' is not a real species"&lt;/span&gt;);&lt;br /&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; Validation.NotApplicable;&lt;br /&gt;    }  &lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;// Note the use of the OR operator here to give a compact syntax for returning a custom error&lt;/span&gt;&lt;br /&gt;    [Validate]&lt;br /&gt;    &lt;span class="kwrd"&gt;protected&lt;/span&gt; Result NumberOfLegsMustBePlausible()&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; NumberOfLegs &amp;lt;= 10 || Validation.Error(&lt;span class="str"&gt;"Your '"&lt;/span&gt; + AnimalName +  &lt;span class="str"&gt;"' has too many legs"&lt;/span&gt;);&lt;br /&gt;    } &lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;span class="rem"&gt;// execute like this&lt;/span&gt;&lt;br /&gt;   &lt;span class="kwrd"&gt;foreach&lt;/span&gt;(Result r &lt;span class="kwrd"&gt;in&lt;/span&gt; Validator&amp;lt;Animal&amp;gt;.ExecuteRulesOn(myAnimal))&lt;br /&gt;     &lt;span class="kwrd"&gt;if&lt;/span&gt;(!r.Pass)&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt;// or, like this, if you don't want to use the generic Validator class&lt;/span&gt;&lt;br /&gt;Validator v = Validator.GetInstanceFor(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Animal));&lt;br /&gt;&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Result r &lt;span class="kwrd"&gt;in&lt;/span&gt; v.ExecuteRulesOn(myAnimal))&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/24760385-2370804097451603149?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/2370804097451603149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/01/readability-in-validation.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/2370804097451603149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/2370804097451603149'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2008/01/readability-in-validation.html' title='Readability in Validation'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-24760385.post-7336175904973793108</id><published>2007-12-29T00:43:00.000-08:00</published><updated>2008-07-15T03:16:33.252-07:00</updated><title type='text'>Interested in POCO LINQ?</title><content type='html'>I've been investigating using LINQ to SQL with a POCO approach.  (&lt;a href="http://en.wikipedia.org/wiki/POCO"&gt;POCO&lt;/a&gt; = Plain Old CLR Objects.)  My ideal solution would be something like this:&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Entity classes are simple enough to be hand-written (no need to generate them with SQL Metal or VS 2008)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Mapping is easy (no need to manually map every property via attributes or external XML)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Lazy-loading works&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Bi-directional relationships work (update one end, and the other is synchronized automatically)&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;The last two points are the most problematical. In LINQ to SQL lazy loading requires the use of EntitySet and EntityRef.  However, it's not easy to use those classes in hand-written code.  In fact, it is generally recommended to &lt;a href="http://blogs.msdn.com/digital_ruminations/archive/2007/08/28/linq-to-sql-poco-support.aspx"&gt;dispense with these classes&lt;/a&gt; if you want to "go POCO".  But that deprives you of lazy loading.  You &lt;a href="http://blogs.msdn.com/mattwar/archive/2007/06/21/linq-to-sql-objects-all-the-way-down.aspx"&gt;also&lt;/a&gt; lose out on Linq’s support for bi-directional relationships, because it is also based on EntitySet and EntityRef.&lt;br /&gt;&lt;br /&gt;I want a solution that supports all four goals outlined above. [&lt;strong&gt;Update&lt;/strong&gt;: &lt;a href="http://www.codeplex.com/Close2Poco"&gt;here&lt;/a&gt; it is]&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Question:&lt;/span&gt; If I can find one, would you be interested in it?  &lt;br /&gt;&lt;br /&gt;If enough people say yes (either in comments below or via email), I’ll try to post something within the next few weeks.  &lt;br /&gt;&lt;br /&gt;I understand that knowledgable people have said this can't be done.  I respectfully disagree ;-)  Based on work so far, I’m satisfied that it &lt;span style="font-style:italic;"&gt;can&lt;/span&gt; be done.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Update:&lt;/span&gt; The idea would be that you'd hand-write .NET classes, according to a few simple conventions. Do that and you'd automatically get working bidirectional relationships and lazy loading, plus automatic runtime generation of the correct mappings. (You'd never use SQL Metal or the Visual LINQ designer.)  &lt;br /&gt;&lt;br /&gt;You could also &lt;span style="font-style:italic;"&gt;generate&lt;/span&gt; the database &lt;span style="font-style:italic;"&gt;if you want&lt;/span&gt;. (I.e. the usual model is generate-code-from-database; this would allow (but not require) generate-database-from-code). If you use TDD, you could create and test the objects using TDD (running in-memory tests) and &lt;span style="font-style:italic;"&gt;then&lt;/span&gt; generate the database. &lt;br /&gt;&lt;br /&gt;Other simple little benefits would be: e.g. could have one file per class (which you can't with MS's generators); could put comments on the properties of those classes (which you can't with MS's generators, as far as I can tell), could put your own &lt;span style="font-style:italic;"&gt;attributes&lt;/span&gt; on the entity/domain object classes, e.g. for attribute-based validation frameworks (again, you can't with MS's generators), entity classes compact enough to actually &lt;span style="font-style:italic;"&gt;read&lt;/span&gt; them ;-)&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Footnote: In this post I’m talking specifically about LINQ to SQL.  I know that there are (or soon will be) several fine independent ORMs that use the LINQ language features to create their queries, but execute those queries with their own backend. A number of these products support POCOs but, for my current project, I need a solution for the full Microsoft "stack" - including LINQ to SQL.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/24760385-7336175904973793108?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/7336175904973793108/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2007/12/interested-in-poco-linq.html#comment-form' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/7336175904973793108'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/7336175904973793108'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2007/12/interested-in-poco-linq.html' title='Interested in POCO LINQ?'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-24760385.post-2652371036824461455</id><published>2007-12-20T23:19:00.000-08:00</published><updated>2007-12-20T23:24:14.807-08:00</updated><title type='text'>Update on Persistent Iterators</title><content type='html'>Some time ago I wrote about &lt;a href="http://dotnet.agilekiwi.com/blog/2007/05/implementing-workflow-with-persistent.html"&gt;implementing workflow with persistent iterators&lt;/a&gt;.  This is just a reminder (in case you missed it in the comments on the original post) that Microsoft are going to change the implementation details.  Until they announce details of the change, we can't be sure whether the technique I posted will work in future versions of C#.  &lt;br /&gt;&lt;br /&gt;Mads Torgersen, the C# Language PM, wrote:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;We are likely to in fact change the way iterators are implemented in future versions. That said, we might be able to implement a serialization format that would work across such future changes. I agree with you that this would be a very useful feature.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;If you want to use this technique in future versions, head over to &lt;a href="https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=278510"&gt;this page&lt;/a&gt; and vote for it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/24760385-2652371036824461455?l=dotnet.agilekiwi.com%2Fblog' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/2652371036824461455/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://dotnet.agilekiwi.com/blog/2007/12/update-on-persistent-iterators.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/2652371036824461455'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/24760385/posts/default/2652371036824461455'/><link rel='alternate' type='text/html' href='http://dotnet.agilekiwi.com/blog/2007/12/update-on-persistent-iterators.html' title='Update on Persistent Iterators'/><author><name>John Rusk</name><uri>http://www.blogger.com/profile/06542045668842804974</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12529563263126069644'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry></feed>