2

I'm at a point in my custom view engine that I want things to be a bit cleaner. One of the ugliest parts I have so far is iif type functionality. It ends up looking like this:

{= CssClass==null ? "" : "class=\""+CssClass+"\"" =}

which compiles(it's a T4 template, so it just generates C# code) to the equivalent of

Write(CssClass==null ? "" : "class=\""+CssClass+"\"");

One way of shortening this I can think of is the ?? operator, but that doesn't help when you have something like Comments.Count==0

I have mostly full control over the generated C# code and what the syntax looks like in a view, so what would be a better way to do this in my design? I'm aiming for something more readable, but also fairly concise. So what syntax modifications should I allow in my view engine to make it looks better?

Earlz
  • 62,085
  • 98
  • 303
  • 499
  • 1
    I don't see what the "problem" with an expression-yielding-if is (read `?:`), although I'd encourage the use of spaces (and outer-parenthesis if it can ever be nested) for readability: e.g. `CssClass==null ? "" : "class=\""+CssClass+"\""` at the very least. –  Mar 21 '11 at 00:19
  • @pst maybe I'm just over-engineering then, but to me the code looks messy. One problem may be that using this kind of syntax forces view designers to be much more familiar with C#, rather than what their core knowledge should be about: HTML, CSS, and Javascript. – Earlz Mar 21 '11 at 00:22
  • Oh, this is for *other* people :P Dunno what T4 allows, but then use a syntax/DSL of choice. Consider Python's `t if e else f` or Scala's `if (e) t else f` (or `if (e) {t} else {f}`) or a Lispish `(if e t f)` or VB's `iff(e, t, f)` perhaps restrict to a *specialized* DSL that offers one-off operations only (e.g. specialized to strings, etc). –  Mar 21 '11 at 00:29
  • Might also be beneficial to see how *other frameworks* handle this sort of thing and to determine exactly *where* the view/logic separation occurs. Happy coding. –  Mar 21 '11 at 00:34
  • @pst well, I have support in my view engine for regular if statements. So I could do `{!if CssClass!=null!} class="{=CssClass=}"{!end!}` a bit more readable, but still a bit messy. There might not be a good solution to my problem with the way my engine is designed. – Earlz Mar 21 '11 at 00:46

1 Answers1

2

Can T4 make use of extension methods?

This is a bit nasty, but it will make the code above a bit more readable. We can make use of the fact that extension methods work even on null references:

public static class MyStringExtensions
{
    public static string ToClassAttribute(this string s)
    {
        return String.IsNullOrWhiteSpace(s) ? String.Empty : "class=\"" + s + "\"";
    }
}

So now your code looks like this:

{= CssClass.ToClassAttribute() =}

If you find that this is too specific and you're doing a lot of HTML attributes as strings like this, you could make a slightly more general version:

public static class MyStringExtensions
{
    public static string ToAttribute(this string s, string attribute)
    {
        return String.IsNullOrWhiteSpace(s) ? String.Empty : attribute + "=\"" + s + "\"";
    }
}

So you could do this sort of thing:

{= CssClass.ToAttribute("class") =}
{= CssStyle.ToAttribute("style") =}

etc.

Matt Hamilton
  • 200,371
  • 61
  • 386
  • 320
  • Oh wow. That's actually very cool. I would bet that it's supported in T4, as the rest of C# is – Earlz Mar 21 '11 at 00:37
  • Also, the way extensions work, it would actually take place in the generated C#, not the actual T4 code – Earlz Mar 21 '11 at 00:58
  • Also, my only criticism is that with this method, I'd have to implement extension methods for everything in HTML practically. I don't think that's a good long term goal – Earlz Mar 21 '11 at 01:13
  • I'll update the answer to make it a *tad* more general for you, Earlz. – Matt Hamilton Mar 21 '11 at 01:16
  • @Matt, ah I didn't think of doing it like that! I did create a `.OnlyIf` extension, but that is much more clean. – Earlz Mar 21 '11 at 01:23
  • That's odd. A tiny caveat. In mono, `IsNullOrWhiteSpace` is a protected method, with it's suitable but not equivalent replacement being `IsNullOrEmpty` – Earlz Mar 21 '11 at 01:27
  • This is the most suitable solution for my current problem, which is HTML attributes. Obviously, my view engine still needs some more syntactic sugar, but this definitely cures this problem in the best way I can imagine at the moment. – Earlz Mar 21 '11 at 01:32