It's exactly what it says on the can.

2008-09-18

Typesafe Reverse Reflection

No, reverse reflection isn't a hall of mirrors. I'm talking about those instances where you need to specify the name of a property of an object which will get used by some component later on to access your object via reflection. Specifically, passing a white-list of property names to ASP.NET MVC's UpdateModel controller method.

Specifying property names in this way has always bugged me. If you decide to change a property name, the compiler can't catch if for you and your program will silently start to fail. What we need, is a way to allow the compiler to catch this situation for you.

The code below shows how this can be achieved for methods and members (properties and fields).

public static class ObjectUtils
{
    public static string GetMemberName<T>(Expression<Func<T, object>> action)
    {
        var lambda = (LambdaExpression)action;
        var unary = (UnaryExpression)lambda.Body;
        var operand = unary.Operand;
        if (ExpressionType.MemberAccess == operand.NodeType)
        {
            var memberExpr = (MemberExpression)operand;
            return memberExpr.Member.Name;
        }
        else if (ExpressionType.Call == operand.NodeType)
        {
            var methodExpr = (MethodCallExpression)operand;
            return methodExpr.Method.Name;
        }
        throw new InvalidOperationException();
    }
}
public class Program
{
    public int SomeInt { get; set; }
    public int getSomeInt() { return SomeInt; }
static void Main()
    {
        string propName = ObjectUtils.GetMemberName<Program>(p => p.SomeInt);
        string funcName = ObjectUtils.GetMemberName<Program>(p => p.getSomeInt());
    }
}

This could be useful in an ASP.NET MVC controller that made a call such as the following:

public interface Product
{
    int Id {get; set; }
    string Name {get; set; }
    decimal UnitPrice {get; set; }
}
public class ProductController : Controller
{
    [AcceptVerbs("POST")]
    public ActionResult Edit(int id, FormCollection fc)
    {
        var entity = dataContext.Products.Single(e => e.Id == id);
UpdateModel(
            entity,
            new[] { "Name", "UnitPrice" }
        );

        // ...
    }
    //...
}

As you can see, in the UpdateModel(...) call we are specifying the 'Name' and 'UnitPrice' properties using a string. Now, if we use GetMemberName method, we can have something that the compiler can understand:

   UpdateModel(
        entity,
        new[] {
            ObjectUtils.GetMemberName<Product>(p => p.Name),
            ObjectUtils.GetMemberName<Product>(p => p.UnitPrice),
        }
    );

My biggest problem with this is that it's very verbose. What I'd really like to do is this:

   UpdateModel(
        entity,
        new[] {
            entity.GetMemberName(e => e.Name),
            entity.GetMemberName(e => e.UnitPrice),
        }
    );

where entity somehow supplies the <Product> type. If anybody has any better ideas, please feel to comment.

2007-10-22

A New Leaf

I started this blog years ago as you can see by the dates of the previous posts. At the time, I didn't really 'get' blogging and I initially tried to use this blog as a way of having my bookmarks available on the web. If only I'd been a bit more pro-active, I might have beaten del.icio.us at their own game! C'est la vie.

I've decided to turn over a new leaf. I now use del.icio.us for my online bookmarks so I can resurrect this blog as an actual blog. I don't intend to be prolific though; I want to keep the subject matter fairly constrained so it will mostly be technical with perhaps a few 'lifestyle' posts here and there. Hope you enjoy it.

2003-12-04

Tiny Skin for Windows Media Player

tBar is a tiny little skin for Windows Media Player that is small enough to sit in the title bar of an app without getting in the way.

2003-11-14

Hot to Create & Apply Patches with GNU diff and patch Tools

"Comparing and Merging Files" describes how to create and apply patches using the GNU diff and patch tools.

2003-11-13

How to Disconnect a VC++ Project from Source Control

180945 - HOWTO: Disconnect a [VC++] Project from Source Control

2003-11-06

21 Well Known Compiler Bugs Ignored by Microsoft?

21 bugs [Was: Re: Well known compiler bugs ignored by Microsoft?]

2003-11-05

The CVS Book

The CVS Book

2003-11-04

Where to Download the WTL

Download details: Windows Template Library (WTL) 7.0

2003-10-23

Is the Current Process a Service?

How to determine if the current process is running as a service (under NT)

2003-10-13

TortoiseCVS

TortoiseCVS is a cool shell extension for Windows operating systems that seriously simplifies access to CVS repositories. It is an open source project at SourceForge.net

The Code Project

The Code Project - Free Source Code and Tutorials