T CastByExample<T>(object o, T example)


So earlier today I was lamenting that an anonymous type can’t be shared between functions with Wes Dyer, when he said “Well actually they can…”

Cue me learning something cool.

The first step is to create a seemingly innocent method:

public static T CastByExample<T>(this object o, T example)
{
    return (T) o;
}

Seems innocent enough right?

Well it is until you start using it with anonymous types. Imagine you had this function, that returns an anonymous type as object, because that is your only choice:

static object GetAnonymousType()
{
    return new { FullName = “Cosmo Kramer” };
}

Normally if you called this function anywhere you wouldn’t be able to get at the anonymous type without using reflection… This is where CastByExample<T> comes to the rescue.

If you know the shape of the anonymous type, you use that to do a CastByExample…

object o = GetAnonymousType();

//get the original anonymous type back again
var v = o.CastByExample(new { FullName = “” });

//Use the properties of the anonymous type initialized in another
//function directly !!
Console.WriteLine(v.FullName);

This works because when an anonymous type is used the compiler first checks that one with the same signature (i.e. all fields are the same name and type) hasn’t already been used. If one has the same CLR type is used.

Hence if you pass in an example that is the same shape as the original anonymous type to the CastByExample<T>(..) method will get you back to the original anonymous type… and var magic does the rest.

Nifty huh?

Comments (15)

  1. Anonymous says:

    匿名对象一般只在同一个Scope中定义和使用,这样才能让VS有Intellisence: 如果是通过函数传递过来的匿名类型对象,就只能用object来传了..当然也就没了Intellis…

  2. littleguru says:

    Hi Alex,

    you should rename:

    o.CastAsType(new { FullName = "" });

    to

    o.CastByExample(new { FullName = "" });

    Greetings,

    Christian

  3. Anonymous says:

    Rick Strahl talks about new C# 3.0 features , but leaves a few questions… Why can’t you change the property

  4. Alex D James says:

    Thanks for the catch little guru…

  5. bittercoder says:

    Thanks for the tip =) I’d always wondered if I could do something like that…

  6. It’s a great idea to use an extension method. I did the same (without extension method) to get the elements of an anonymous typed List. What is funny in my sample is that I create the List using reflection, so without use an IEnumerable first.

    http://blog.developpez.com/index.php?blog=121&title=c_3_0_creer_une_liste_de_types_anonymes&more=1&c=1&tb=1&pb=1

  7. Anonymous says:

    One of the biggest limitation in “var” is that it cannot be shared across the methods. So if you are

  8. Anonymous says:

    Did you try to cast anonymous types (vars)? You are. However, you never was able to pass var from one

  9. Anonymous says:

    I was reading this particular entry from AlexJ&#39;s blog, in which he discussed how to use anonymous

  10. aelij says:

    Great tip! I also added to these two:

    public static IEnumerable<T> CastByExample<T>(this IEnumerable o, T example)

    {

       return (IEnumerable<T>)o;

    }

    public static IQueryable<T> CastByExample<T>(this IQueryable o, T example)

    {

       return (IQueryable<T>)o;

    }

    Now I can create methods that return the non-generic IEnumerable and IQueryable interfaces.

  11. Anonymous says:

    You’ve been kicked (a good thing) – Trackback from DotNetKicks.com

  12. Anonymous says:

    [This blog was migrated. You will not be able to comment here. The new URL of this post is http://khason

  13. Anonymous says:

    Alex and Eli Arbel

    Your extension methods are big help when working on EF level and want to use  functions which may return

    anonymous type (or IEnumerable<anonymous type>)

    Thanks!

  14. Anonymous says:

    Awesome!!.. I was having a bad day with anonymous types.. as result of an lambda expression via LinQ to SQL.

    Thank you for this useful tip.

    Cheers.

    CQ