Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Anonymous types to an array of objects?

I have this anonymous type :

var t= new {a=1,b="lalala",c=DateTime.Now};

How can I make it an array of Objects ( each element -> cast to object)

hence to something like :

object[]  v = new object[] {1,"lalala",DateTime.Now};

edit

p.s. this is just a knowledge question about learning to convert from 1 type to other. i know i can initialize an array of object from the beginning. but this is a learning question.

sorry for not mentioned it.

order Is important...why? cause ConstructorInfo.Invoke is accepting

Type: System.Object[] An array of values that matches the number, order (!!!) and type (under the constraints of the default binder) of the parameters for this ....

like image 359
Royi Namir Avatar asked Jun 26 '12 17:06

Royi Namir


1 Answers

You'd have to use reflection, basically. It shouldn't be too hard via Type.GetProperties, but I don't know of anything "built-in".

As leppie pointed out, the ordering isn't simple - you'd have to examine the order of the parameters, which would at least give you the order of all the types of the properties. If you only had different types, that would be fine.

If you don't care about the ordering, you can use:

var array = t.GetType()
             .GetProperties()
             .Select(p => p.GetValue(t, null))
             .ToArray();

EDIT: I've just thought of something which will actually fix it, but it's implementation specific. The C# compiler generates anonymous types using generic types. So new { A = 5, B = "foo" } will actually create an anonymous type like this:

class <>_Anon<TA, TB>
{
    internal <>_Anon(TA a, TB b)
}

so you can work out the property names in order based on the generic types of the generic properties, then fetch the properties in order from the concrete type. But it's ugly...

using System;
using System.Linq;
using System.Reflection;

class Test    
{
    // Note: this uses implementation details of anonymous
    // types, and is basically horrible.
    static object[] ConvertAnonymousType(object value)
    {
        // TODO: Validation that it's really an anonymous type
        Type type = value.GetType();
        var genericType = type.GetGenericTypeDefinition();
        var parameterTypes = genericType.GetConstructors()[0]
                                        .GetParameters()
                                        .Select(p => p.ParameterType)
                                        .ToList();
        var propertyNames = genericType.GetProperties()
                                       .OrderBy(p => parameterTypes.IndexOf(p.PropertyType))
                                       .Select(p => p.Name);

        return propertyNames.Select(name => type.GetProperty(name)
                                                .GetValue(value, null))
                            .ToArray();

    }

    static void Main()
    {
        var value = new { A = "a", Z = 10, C = "c" };
        var array = ConvertAnonymousType(value);
        foreach (var item in array)
        {
            Console.WriteLine(item); // "a", 10, "c"
        }
    }
}
like image 88
Jon Skeet Avatar answered Oct 20 '22 00:10

Jon Skeet