Cast to Anonymous Type

∥☆過路亽.° 提交于 2019-11-26 10:29:40
Lasse Vågsæther Karlsen

Note, as per the comment, I'd just like to point out that I too recommend using a real type when you need to pass it around the program like this. Anonymous types should only really be used locally in a single method at a time (in my opinion), but anyway, here's the rest of my answer.


You can do it using a trick, by tricking the compiler into inferring the right type for you:

using System;

namespace ConsoleApplication4
{
    class Program
    {
        static void Main(string[] args)
        {
            var a = new { Id = 1, Name = "Bob" };
            TestMethod(a);

            Console.Out.WriteLine("Press enter to exit...");
            Console.In.ReadLine();
        }

        private static void TestMethod(Object x)
        {
            // This is a dummy value, just to get 'a' to be of the right type
            var a = new { Id = 0, Name = "" };
            a = Cast(a, x);
            Console.Out.WriteLine(a.Id + ": " + a.Name);
        }

        private static T Cast<T>(T typeHolder, Object x)
        {
            // typeHolder above is just for compiler magic
            // to infer the type to cast x to
            return (T)x;
        }
    }
}

The trick is that inside the assembly, the same anonymous type (same properties, same order) resolves to the same type, which makes the trick above work.

private static T CastTo<T>(this Object value, T targetType)
{
    // targetType above is just for compiler magic
    // to infer the type to cast value to
    return (T)value;
}

usage:

var value = x.CastTo(a);

But we're really pushing the limits here. Use a real type, it'll look and feel cleaner as well.

Instead of casting to your custom type try using dynamic type.

Your event handler would look something like this:

private void cmdOK_Click(object sender, EventArgs e)
{
    dynamic option = bsOptions.Current;
    if (option.Id == 1) { doSomething(); }
      else { doSomethingElse(); }
}

To quote MSDN:

An anonymous type cannot be cast to any interface or type except for object.

In C# 3.0, this is not possible. You'll have to wait for C# 4.0, which allows accessing properties at runtime using "dynamic" variables.

public class MyExtensMethods{

    public static T GetPropertyValue<T>(this Object obj, string property)
    {
        return (T)obj.GetType().GetProperty(property).GetValue(obj, null);
    }
}

class SomeClass
{
    public int ID{get;set;}
    public int FullName{get;set;}
}


// casts obj to type SomeClass
public SomeClass CastToSomeClass(object obj)
{
     return new SomeClass()
     {
         ID = obj.GetPropertyValue<int>("Id"),
         FullName = obj.GetPropertyValue<string>("LastName") + ", " + obj.GetPropertyValue<string>("FirstName")
     };
}

.... then to cast you will do:

var a = new { Id = 1, FirstName = "Bob", LastName="Nam" };
SomeClass myNewVar = CastToSomeClass(a);

you can try this:

private void cmdOK_Click(object sender, EventArgs e)
{
    var option = Cast(bsOptions.Current, new { Id = 0, Option = "", Description = "" });
}

see: Can't return anonymous type from method? Really?

You can also declare an array of anonymous Types directly with that syntax:

var data = new [] {
  new {Id = 0, Name = "Foo"},
  new {Id = 42, Name = "Bar"},
};
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!