Array of dynamic | ExpandoObject | with a compressed initialize syntax
Asked Answered
D

3

10

Im trying to use DynamicObject in c#, and I needed an array of dynamic:

var d = new dynamic[];

which works fine.

EDIT : See ExpandoObject below.

But I also like to fill that array with some data with this compressed initialize new syntax:

var d = new dynamic[] { 
  new {
   Name = "Some",
   Number = 1010
  },
  new {
   Name = "Other",
   Number = 2010
  }
 }

But in that case all objects gets the non-dynamic type "object" and a loop through the items will give me an exception:

foreach (dynamic item in d)
{
  @item.Name
  @item.Number
}

Error : 'object' does not contain a definition for 'Name'. I guess I just initialize the array items the wrong way. How to add dynamic objects instead?

EDIT: New content:

I realize "dynamic" does not have the capability to dynamically add properties.

I better be using ExpandoObject which exposes all items in an an internal dictionary as properties. But unfortunately ExpandoObject does not seem to support this nice compressed create syntax, and the compiler complains:

var d = new ExpandoObject[]{
new ExpandoObject(){
    Name="Nnn",
    Number=1080
    }
}

So the answer might just be : it's not possible.

Doorstone answered 26/1, 2011 at 14:39 Comment(8)
Are you sure you don't just want an array of an anonymous-type?Indwell
Is this in ASP.NET MVC3?Lizalizabeth
Bear in mind that a dynamic is an object, just that the C# compiler treats it differently and farms all accesses on dynamic off to the DLRTosspot
The foreach is using Razor yes. And anonymous type - yes, if it works, I get the same error there - thats when I tried dynamic instead :)Doorstone
@joeriks: Have you tried an explicit cast on each element of the array? It is a little nasty but it might work.Hallucination
yes - thanks - see my comment to Snowbear.Doorstone
I dont get this error at all. Your first code block should work just fine. It is it something very specific to your framework? Like it doesn't work in Razor view of ASP.NET MVC? In normal code that C# is just fine.Secession
As to how to fake object initializer syntax for Expandos, see #4216809, #5910831Secession
S
7

I come a bit late but here is what i found about it :

if I can't initialise an ExpandoObject, how about initialising it with a dynamic type ?

so i did the following extension method

    public static ExpandoObject CreateExpando(this object item)
    {

        var dictionary = new ExpandoObject() as IDictionary<string, object>;
        foreach (var propertyInfo in item.GetType().GetProperties())
        {
            dictionary.Add(propertyInfo.Name, propertyInfo.GetValue(item, null));
        }
        return (ExpandoObject)dictionary;
    }

I know it's far from ideal, but it's the best I could achieve for now, it works like this :

var myExpandoObject = new { Name="Alex", Age=30}.CreateExpando();
Supererogation answered 14/9, 2011 at 8:52 Comment(1)
Can I use this extension method if my projection is stored in a function? eg: someQueryable.Select(ReusableProjection().ToExpando()), where ReusableProjection returns this: Expression<Func<SomeType, dynamic>>Psalms
R
11

Hopefully you do not really need dynamics

class Program
{
    static void Main(string[] args)
    {
        var d = new[]
                    {
                        new
                            {
                                Name = "Some",
                                Number = 1010
                            },
                        new
                            {
                                Name = "Other",
                                Number = 2010
                            }
                    };
        foreach (var item in d)
        {
            string s = @item.Name;
            int n = @item.Number;
            Console.WriteLine("{0} {1}", s, n);
        }
    }
}
Rubrician answered 26/1, 2011 at 14:45 Comment(6)
Yes, so I thought, and I tried that too - but that gives me the same error. Hmm...Doorstone
@Doorstone - added entire code fragment which I was launching, I do not have any errors.Rubrician
@Doorstone - if it is related to ASP.Net MVC then probably you should tag the question accordingly. I'm not sure how my answer correlates with Razor behavior.Rubrician
Yes - it's indeed related to my context someway. The thing is I send the array as a member of a Page dynamic object. When I - like you - run in one and the same class all is fine. And - the only thing I find differs on the d object between the working code and my real one is that in the working code sample a GetType returns <>f__AnonymousType02[System.String,System.String][] but in my real code a GetType returns <>f__AnonymousType12[System.String,System.String][]. (Which is also what differs when I perform a ToString on the object). Now does that 1 / 0 do for my object?Doorstone
I think the problem with the Anonymous type in this case is the same as described here tomasp.net/blog/cannot-return-anonymous-type-from-method.aspx - which brings me back to my original question, can I do it in a nice way with dynamic instead?Doorstone
@Doorstone - 1/0 doesn't matter - as far as I know it is just a counter for anonymous classes so they will all have different names. And it means that you already have another anonymous class in your real code. Sorry, can't help you with MVC, hopefully somebody else will.Rubrician
S
7

I come a bit late but here is what i found about it :

if I can't initialise an ExpandoObject, how about initialising it with a dynamic type ?

so i did the following extension method

    public static ExpandoObject CreateExpando(this object item)
    {

        var dictionary = new ExpandoObject() as IDictionary<string, object>;
        foreach (var propertyInfo in item.GetType().GetProperties())
        {
            dictionary.Add(propertyInfo.Name, propertyInfo.GetValue(item, null));
        }
        return (ExpandoObject)dictionary;
    }

I know it's far from ideal, but it's the best I could achieve for now, it works like this :

var myExpandoObject = new { Name="Alex", Age=30}.CreateExpando();
Supererogation answered 14/9, 2011 at 8:52 Comment(1)
Can I use this extension method if my projection is stored in a function? eg: someQueryable.Select(ReusableProjection().ToExpando()), where ReusableProjection returns this: Expression<Func<SomeType, dynamic>>Psalms
M
1

The open source framework Impromptu-Interface has a compressed initialization syntax that works with ExpandoObject.

dynamic @new = Builder.New<ExpandoObject>();

var d = @new.List( 
  @new.Expando(
   Name:"Some",
   Number: 1010
  ),
  @new.Expando(
   Name:"Other",
   Number: 2010
  )
 );
Malfunction answered 21/4, 2011 at 3:7 Comment(1)
Cool, I'll give Impromptu a look.Doorstone

© 2022 - 2024 — McMap. All rights reserved.