Category Archives: Uncategorized

Code generation with Roslyn

I recently wrote an answer on StackOverflow.com regarding what I’ve learned doing code generation with Roslyn.

My conclusion after a few weeks playing around is that using a combination of inline code snippets (parsed using CSharpSyntaxTree.ParseText) and manually generated SyntaxNodes, works well. But I felt a strong preference for the former. I have also used T4 in the past but am moving away from them due to general lack of integration & capability. I compare the three approaches below and conclude with some tips about doing code gen with Roslyn:

Advantages/disadvantages of each:

Roslyn ParseText

  • Generates arguably more readable code-generator code.
  • Allows ‘text templating’ approach e.g. using C# 6 string interpolation.
  • Less verbose.
  • Guarantees valid syntax trees.
  • Can be more performant.
  • Easier to get started.
  • Text can become harder to read than SyntaxNodes if majority is procedural.

Roslyn SyntaxNode building

  • Better for transforming existing syntax trees – no need to start from scratch.
    • But existing trivia can make this confusing/complex.
  • More verbose. Arguably harder to read and build.
    • Syntax trees are often more complex than you imagine
  • SyntaxFactory API provides guidance on valid syntax.
  • Roslyn Quoter helps you transform textual code to factory code.
  • Syntax trees are not necessarily valid.
  • Code is perhaps more robust once written.

T4 templates

  • Good if majority of code to be generated is boiler plate.
  • No proper CI support.
  • No syntax highlighting or intellisense without 3rd party extensions.
  • One to one mapping between input and output files.
    • Not ideal if you are doing more complex generation e.g. entire class hierarchy based on single input.
  • Still probably want to use Roslyn to “reflect” on input types, otherwise you will get into trouble with System.Reflection and file locks etc.
  • Less discoverable API. T4 includes, parameters etc. can be confusing to learn.

Roslyn code-gen tips

  • If you are only parsing snippets of code e.g. method statements, then you will need to use CSharpParseOptions.Default.WithKind(SourceCodeKind.Script) to get the right syntax nodes back.
  • If you are parsing a whole block of code for a method body then you will want to parse it as a GlobalStatementSyntax and then access the Statement property as a BlockSyntax.
  • Use a helper method to parse single SyntaxNodes:
        private static TSyntax ParseText<TSyntax>(string code, bool asScript = false)
        {
            var options = asScript
                ? CSharpParseOptions.Default.WithKind(SourceCodeKind.Script)
                : CSharpParseOptions.Default;
    
            var syntaxNodes =
                CSharpSyntaxTree.ParseText(code, options)
                    .GetRoot()
                    .ChildNodes();
    
            return syntaxNodes.OfType<TSyntax>().First();
        }
  • When building SyntaxNodes by hand you will typically want to make a final call to SyntaxTree.NormalizeWhitespace(elasticTrivia: true) to make the code “round-trippable”.
  • Typically you will want to use SyntaxNode.ToFullString() to get the actual code text including trivia.
  • Use SyntaxTree.WithFilePath() as a convenient place to store the eventual file name for when you come to write out the code.
  • If your goal is to output source files, the end game is to end up with valid CompilationUnitSyntaxs.
  • Don’t forget to pretty-print using Formatter.Format as one of the final steps.

The Economics of Microsoft Surface

This is a post I wrote August 2009 but never got around to publishing. Whilst spring cleaning my drafts, I re-read it and decided it wasn’t that bad, so here it is. I wonder if the issues are still the same in 2011….

——————–

It’s almost a year ago to the month that Amnesia Razorfish smuggled the first Microsoft Surface tables into Australia with the help of parent company Razorfish, much to the excitement of local geeks. There was also a fair bit of uproar from surprised parties who hadn’t expected to be usurped in such spectacular fashion.

I was hired by Amnesia shortly before Surface arrived, partly on speculation that they would soon need a Surface developer. I had experience with the technologies it uses, and a great interest in the product, so was really excited to get such an opportunity. It was also a bit of a gamble on my part, as it was by no means guaranteed at the time they would even be getting a table, let alone any paying clients.

The first few weeks, maybe months, there was a great buzz and curiosity from clients and media about this new device. The phones were ringing off the hook and there were regular coffee table tours.

Despite this, and the amazing stock of talent Amnesia had at its disposal, I think it’s safe to say that during my year there, they never needed more than this one, solitary, Surface developer.

How can that be? “Surely it would be as easy as selling antifreeze to Eskimos!”, I hear you mutter…

Here’s why: In many scenarios, the economics of Surface development simply don’t add up.

For background, let’s put a few ballpark figures on the coffee table:

– Cost of a MS Surface table: $10k
– Cost of  development/design time: $200/hour

Let’s tackle the most obvious thing first: This Is Software Development.

It’s been many years since the Adobe Flash experiences that draw crowds on the web have been built entirely with a visual tool. Most are chock full of ActionScript. In fact, dare I say, they probably contain more programming hours than design hours.

Suffice to say there are very few digital experiences of the richness that people expect these days, that can be built without significant software development capabilities, and that goes for Microsoft Surface too.

Microsoft Surface carries the extra burden of not only having slightly less mature tools than industry mainstay Adobe Flash, but more importantly having a much smaller experience pool, particularly in the crucial “devigner” niche. And as with any new technology, the early days often mean higher costs and higher risks.

So, creating a quality Surface experience means building software. But what do you get for your money? Well it could easily cost you $6000 per man week, and even after many weeks development the chances are you won’t get that award winning experience you were hoping for. My guess is that most commercial Surface applications you see being touted cost in the region of $300,000. Definitely in the hundreds of thousands. Let your imagination go wild and you could easily spend half a million.

The next most obvious thing is: Penetration.

Unlike building a user experience for the web, prospective clients will be footing the bill for each and every device that will end up in front of users. If you are going to pay a hefty sum for bespoke software development you sure as hell want to leverage that investment by deploying it to the maximum number of locations.

You can keep the costs low by only having a tiny number of tables (and maybe even spin that to your boss by claiming the experience would then be truly unique/exclusive!), but ultimately you are talking about investing in a piece of custom-written software that will only ever be seen by a tiny audience. Yes, that might be tenable for a small number of luxury brands, but for the majority who actually need to justify there expenditure? I think not.

So, to get “good value” from your investment in a Surface experience you need to also purchase a reasonably large number of tables. I would say at least in the tens if not hundreds (e.g. retail locations). There’s $500,000 right there.

Lastly: Cost/benefit.

At the end of the day, clients have to estimate how much a Surface experience is going to be worth to them. It’s obvious that many applications of Surface can be categorized as marketing in some sense; whether its experiential branding, attractive gimmick, or 9 o’clock news hype.

I can only imagine it’s very hard to estimate the financial benefits such a Surface experience will bring, because in the majority of cases it’s going to be an indirect effect at best. And such financial benefits are almost certainly going to be impossible to determine a-priori.

Which is also the case if Surface is used as Point-of-Sale platform – it’s all pretty much undiscovered country. With such little data on natural user interfaces, not to mention Surface specifically, it’s very hard at this stage to make confident guesses about how conversion rates or stickiness can be improved. The only way to find out for sure is by putting down the cash. And that’s a risk many firms can’t or wont take.

Microsoft Surface development goes public

At PDC this year Microsoft announced that Surface development resources were going to be made publicly available. (Up until now it had been an “invitation only” system).

This is great news and means anyone can build or prototype Surface applications. The Surface SDK comes with a very good simulator. A table is still needed to evaluate performance and usability, but you can go a long way with just the simulator.

Microsoft Surface Simulator

Here is a copy & paste from a recent mail-out:

  • Surface Web site (http://www.surface.com)
  • MSDN (http://msdn.microsoft.com)
  • TechNet (http://technet.microsoft.com)
  • Microsoft Download center (http://www.microsoft.com/downloads)
    • A new product category for all Surface downloads, including the Surface SDK Workstation Edition, applications, documentation, and any software fixes.
  • Microsoft Support (http://support.microsoft.com)
  • WCF Data Services vs WCF RIA Services

    I’ve been having trouble finding a straight forward comparison of these two technologies. On the surface they appear to be solving similar, if not the same problems.

    Make no mistake – the message coming from Microsoft is not clear or consistent – which probably explains the confusion. I suspect the relationship between these two products is still being “discovered” by MS.

    Anyway, in this bliki I will try to sum up my findings as to the differences between them as I figure them out.

    WCF (ADO.NET) Data Services

    WCF (.NET) RIA Services

    Expose data model as RESTful web service Prescriptive approach to n-tier app development
    Cross platform interoperation as a goal
    – “Unlock data silos”
    – Out-of-box support from future MS products such as SQL2008 R2, Azure, Excel 2010, SharePoint 2010
    Designed specifically for end-to-end Silverlight & ASP.NET solutions
    – Some technology proprietary to Silverlight (no WPF support)
    – Use ASP.NET Authentication/Roles across SL and ASP.NET
    – ASP.NET/AJAX can also access service layer
    Loosely coupled clients and servers Client & server are designed and deployed together
    Service layer exposes “raw” data sources Opportunity to easily add business logic into service layer
    – Encourage “domain” concepts
    – Strong validation framework
    – Offline / Sync enabled
    Service can be consumed from .NET, Silverlight, AJAX, PHP and Java (libraries available) Service can be consumed easily from SL, AJAX, WebForms
    Service’s data source must:
    – Expose at least one IQueryable property
    – Implement IUpdateable if you desire updates
    Service exposes domain objects via convention:
    – IQueryable GetX
    – UpdateX/InsertX/DeleteX
    No design time experience yet (??) Design time experience with data sources, drag drop etc
    – OData for all clients
    – Within OData, multiple formats supported (JSON, XML etc)
    – SOAP (binary) for SL clients
    – JSON for AJAX clients
    – SOAP (XML) for other clients
    Discoverable (?) Non-discoverable
    Hosted as WCF Service (.svc) Old version hosted in custom web handler (.axd).
    New version is WCF service.
    Standardized on OData protocol Will “support” OData
    More mature – public for at least 2 years, formerly “Project Astoria” Less mature – public for 6 months


    Common features

    • Based on WCF
    • Use a RESTful architecture
    • Can be used to expose any data source (sql, xml, poco/objects etc.)
    • Client side libraries provide ability to query using LINQ

    General

    • Currently they do not share much (any?) technology / code
    • RIA Services is not based on top of Data Services
    • RIA Services & Data Services will “align”
    • OData eventually pushed down into WCF stack

    Your opinions are welcome!

    References

    http://blogs.msdn.com/brada/archive/2009/03/19/what-is-net-ria-services.aspx

    http://mschannel9.vo.msecnd.net/o9/mix/09/pptx/t36f.pptx

    http://blogs.msdn.com/endpoint/archive/2009/11/18/the-wcf-services-ecosystem.aspx

    http://www.douglaspurdy.com/2009/11/20/on-odata-open-data-protocol/

    http://msdn.microsoft.com/en-us/data/ee844254.aspx

    http://blogs.msdn.com/saurabh/archive/2009/11/23/understanding-the-wcf-in-wcf-ria-services.aspx

    Expression Blend 3 Help: The missing DelegateCommand class

    Some tutorials from the Expression Blend 3 help docs (e.g. “Try it: Display data from a sample SQL database”, which is based on these two articles) require a class that is present in the ColorSwatch WPF sample. The problem is that someone appears to have forgotten to bundle the ColorSwatch sample with the Blend 3!

    To save you the hassle of trying to track down the DelegateCommand class here it is:

    using System; 
    using System.Collections.Generic; 
    using System.Text; 
    using System.Windows.Input; 
     
    namespace ColorSwatch 
    { 
        public sealed class DelegateCommand : ICommand 
        { 
            public delegate void SimpleEventHandler(); 
     
            private SimpleEventHandler handler; 
     
            private bool isEnabled = true; 
     
            public DelegateCommand(SimpleEventHandler handler) 
            { 
                this.handler = handler; 
            } 
     
            #region ICommand implementation 
     
            void ICommand.Execute(object arg) 
            { 
                this.handler(); 
            } 
     
            bool ICommand.CanExecute(object arg) 
            { 
                return this.IsEnabled; 
            } 
     
            public event EventHandler CanExecuteChanged; 
     
            #endregion 
     
            public bool IsEnabled 
            { 
                get { return this.isEnabled; } 
                set 
                { 
                    this.isEnabled = value; 
                    this.OnCanExecuteChanged(); 
                } 
            } 
     
            private void OnCanExecuteChanged() 
            { 
                if (this.CanExecuteChanged != null) 
                { 
                    this.CanExecuteChanged(this, EventArgs.Empty); 
                } 
            } 
        } 
    }