Question

Here is my code:

MyClass here = new MyClass();
IEnumerable<MyClass> vats = (IEnumerable<MyClass>)here.All();

The All() method returns IEnumerable<dynamic>. I want to convert it to IEnumerable<MyClass>. The line above doesn;t work, it says Unable to cast object of type 'd__15' to type 'System.Collections.Generic.IEnumerable`1[MyClass]'.

I also tried:

 IEnumerable<MyClass> vats = here.All() as IEnumerable<MyClass>;

but it returns null.

Was it helpful?

Solution

Similar to dbaseman's answer (and AKX's comment) I'd use Cast:

IEnumerable<MyClass> vats = here.All().Cast<MyClass>();

You'll need a using directive for LINQ though:

using System.Linq;

at the top of your file. It sounds like you haven't got that if the Select method isn't recognized.

Note that this assumes that each value really is a MyClass reference.

EDIT: If you want to be able to access the values by index, I'd recommend using ToList:

List<MyClass> vats = here.All().Cast<MyClass>().ToList();

While ToArray would work too, I personally favour lists over arrays in most cases, as they're rather more flexible.

EDIT: It sounds like your results are actually full of ExpandoObject. You'll need to create a new instance of MyClass from each item, e.g.

List<MyClass> vats = here.All()
                         .Select(item => new MyClass(item.Name, item.Value))
                         .ToList();

or possibly:

List<MyClass> vats = here.All()
                         .Select(item => new MyClass {
                                     Name = item.Name,
                                     Value = item.Value,
                                 })
                         .ToList();

That's just an example, which I wouldn't expect to work straight away - we can't do any better than that as we know nothing about how your results are actually being returned.

It does sound like you're in over your head here, I'm afraid.

OTHER TIPS

You just have to cast each individual object:

MyClass[] vats = here.All().Select(item => (MyClass)(dynamic)item).ToArray();

The first thing to work out before you can create a solution is what types the objects will have at run time. Seeing from your comments that they are going to be ExpandoObjects and assuming MyClass does not derive from ExpandoObject you can't use the .Cast<T> method since it only supports casts and not custom conversions.

There's a trick you can use to convert from ExpandoObjects using the JavaScriptSerializer

taking from this link here an extension method that you could use

public static IEnumerable<T> Convert<T>(this IEnumerable<dynamic> self){
    var jsSerializer = new JavaScriptSerializer();
    foreach(var obj in self){
        yield return jsSerializer.ConvertToType<T>(obj);
    }
}

in your case then all you have to do is change the Cast in skeets answer to Convert.

List<MyClass> vats = here.All().Convert<MyClass>().ToList();

This is a bit hackish since the JavaScriptSerializer was not meant to do this but it does solve the problem.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top