24

Presently in LINQ, the following compiles and works just fine:

var listOfFoo = myData.Select(x => new FooModel{
     someProperty = x.prop1,
     someOtherProperty = x.prop2
});

public class FooModel{
     public string someProperty  { get; set; };
     public string someOtherProperty  { get; set; };
}

However, the past few versions of .NET/C# have expanded the role of dynamic objects such as the ExpandoObject and I am wondering if there is a way to basically do this:

var listOfFoo = myData.Select(x => new ExpandoObject{
     someProperty = x.prop1,
     someOtherProperty = x.prop2
});

Obviously, I have already tried the code above without success, but it seems like I am missing something.

Matt Cashatt
  • 23,490
  • 28
  • 78
  • 111

3 Answers3

45

You should be able to create a new anonymous object without any type declared:

var listOfFoo = myData.Select(x => new {
    someProperty = x.prop1,
    someOtherProperty = x.prop2
});
CassOnMars
  • 6,153
  • 2
  • 32
  • 47
  • D'oh! Man I feel dumb. Yes, it was this easy. Can accept answer in 6 minutes. Thanks! – Matt Cashatt Mar 21 '13 at 18:14
  • 6
    @MatthewPatrickCashatt Note that there is nothing dynamic about the object. The object that is defined here is statically typed and even immutable as well. Now if that's suitable for your needs, that's great, but if you really wanted what you asked for in the question, then this isn't it. – Servy Mar 21 '13 at 18:17
  • Thanks, @Servy. I appreciate your answer as well. What is confusing to me in regards to your comment, however, is that @d_r_w's approach still let's me add dynamic properties to the object. For example, `foreach(dynamic item in listOfFoo{ item.someNewProperty = "bar" }` works fine. What am I missing? – Matt Cashatt Mar 21 '13 at 18:31
  • @MatthewPatrickCashatt Just because it *compiles* doesn't mean it *works*. Using `dynamic` is essentially turning off the compiler (or most of it, anyway) so you're not going to get compile time errors even if the code is not going to work at all at runtime. – Servy Mar 21 '13 at 18:38
  • As an additional note, by not using the `dynamic` keyword in your selection of said anonymous object, you can keep the type checking of your compiler, so when you're accessing `someProperty` or `someOtherProperty`, the compiler will verify all operations on it are conformant to the type of the property. – CassOnMars Mar 21 '13 at 18:44
12

There is nothing preventing you from using Select to return a collection of ExpandoObject's, you just aren't properly constructing the ExpandoObject. Here's one way:

var listOfFoo = myData.Select(x =>
    {
        dynamic expando = new ExpandoObject();
        expando.someProperty = x.prop1;
        expando.someOtherProperty = x.prop2;
        return (ExpandoObject)expando;
    });
Servy
  • 202,030
  • 26
  • 332
  • 449
  • 3
    I don't think that will work without converting to an IEnumerable. – Erik Funkenbusch Mar 21 '13 at 18:21
  • @MystereMan Converting what to an `IEnumerable`? – Servy Mar 21 '13 at 18:21
  • Converting the EF IQueryable (I assume it's not Linq to objects). I don't think the ExpandoObject code will be convertible to SQL, so it would likely generate an EF error. You would have to convert the results to IEnumerable to do it. – Erik Funkenbusch Mar 21 '13 at 18:38
  • @MystereMan What makes you think that `myData` is an `IQueryable`? There's nothing in the question that seems to indicate that to me. If it is indeed an `IQueryable` then yes, you'd need to add an `AsEnumerable` in there to run this on the client side. – Servy Mar 21 '13 at 18:40
  • In my experience, the vast majority of questions about linq are related to either EF or L2S, there's also nothing in the question to indicate it's L2O's so either assumption is invalid. – Erik Funkenbusch Mar 21 '13 at 19:21
  • @MystereMan `In my experience, the vast majority of questions about linq are related to either EF or L2S` In my experience that's not the case at all. Additionally, when it is being used it's frequently clear through the variable names that the source data is coming from a data context, as you see `context.Order`, `ctx.Data`, or else something like that. There's also a responsibility to indicate which query provider is being used, if the question relates to one, whereas it's a question that doesn't apply at all to L2O. – Servy Mar 21 '13 at 19:25
  • Casting should be to dynamic or skipped: `return expando;` – Todd Feb 09 '17 at 14:12
  • @Todd The question specifically asked how to get a sequence of `ExpandoObjects`, not a sequence of `dynamic` which happened to actually contain expando objects. – Servy Feb 09 '17 at 14:17
  • @ Servy Yes but with ExpandoObject casting `listOfFoo` is useless(you can't access `someProperty` and `someOtherProperty` that way without additional casting to dynamic) – Todd Mar 02 '17 at 15:23
  • @Todd Of course you can. It's just a dictionary under the hood, and you can access the data as such. Just because you *can* access the data through `dynamic` doesn't mean you *have* to. – Servy Mar 02 '17 at 15:24
  • No, I can not. It throws compilation error `'ExpandoObject' does not contain a definition for 'someProperty' and no extension method 'someProperty' accepting a first argument of type 'ExpandoObject' could be found (are you missing a using directive or an assembly reference?)` – Todd Mar 02 '17 at 15:33
  • 1
    @Todd Yes, if you try to access the data as a property, it won't work, because the object doesn't have that property, it's just faking it when using `dynamic`. Like I said, if you access the data as data in a collection, which is what it is, then it will work just fine. – Servy Mar 02 '17 at 15:34
  • @ Servy Yes, on the ground that `ExpandoObject` inherits `ICollection> ` as well as `IDictionary` and so on but that was not my point. I gave you thumbs up for your answer anyway. :) – Todd Mar 02 '17 at 16:06
  • @Todd No, it wasn't your point *it was my point*. The OP asked for a sequence of expando objects. You said that getting a sequence of expando objects is useless and that they need to be cast to `dynamic` to get the data. That's wrong, you don't need to cast it to get the data, that's just *one way* to get the data. – Servy Mar 02 '17 at 16:08
  • @ Servy OK, this is one of the ways to get the data, on that I agree and it is incorrect to call it useless, but for me(my opinion) this is the logical/fastest/cleanest way to use the data in `listOfFoo`(in aspect of writing my code),but I guess that everything depends on the case what `listOfFoo` is needed for... – Todd Mar 02 '17 at 16:29
  • @Todd Your personal preference may be to use `dynamic` but the question *specifically* asked to get a sequence of `ExpandoObject` objects, which is an entirely reasonable request, even if you personally don't like it, so that's what I provided in an answer. – Servy Mar 02 '17 at 16:35
  • @ Servy Well... The question is in the title and asks "to output a dynamic object from a Select statement" The code snippet in the description I take it more like pseudo code to express what author intends to do(but this only author can tell). Don't get me wrong man, I don't mean to offend you or anything alike (if so I apologize), only wanted to be helpful with my comments and I do it not for points/badges or to troll your answer, so peace. – Todd Mar 02 '17 at 17:15
0
using (var command = this._context.Database.GetDbConnection().CreateCommand())
        {
            command.CommandText = "select * from persons";
            command.CommandType = CommandType.Text;
            this._context.Database.OpenConnection();
            using (var result = command.ExecuteReader())
            {
                var lst = new List<object>();
                var lstColumns = new UserAccount().GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).ToList();
                while (result.Read())
                {
                    var newObject = new object();
                    dynamic myobject = new ExpandoObject();
                    IDictionary<string, object> myUnderlyingObject = myobject;
                    for (var i = 0; i < result.FieldCount; i++)
                    {
                        var name = result.GetName(i);
                        var val = result.IsDBNull(i) ? null : result[i];
                        myUnderlyingObject.Add(name, val);
                    }
                    lst.Add(myUnderlyingObject);
                }
                return Ok(lst);
            }
        }
  • this is a very complicated solution to a very simple request that was asked and answered almost 10 years ago. To provide a new answer now you should include supportive arguments why this solution is superior to the other existing ones, but here you've gone back to first principals to do in 25 lines of code what you could have done in a single Linq expression? – Chris Schaller Sep 14 '21 at 14:16
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-ask). – Community Sep 14 '21 at 14:24
  • This is a good starting point. Thank you. – Robert Smith Dec 27 '21 at 21:10