Error when trying to cast anonymous object, Razor

2019-04-16 16:41发布

问题:

I am trying to cast an array of anonymous objects, where each object looks like this:

new {type="internal",title="Linktitle",target="_blank",link="http://www.google.se"}

I have declared a Class "Link", to which the anonymous objects should be casted

class Link{
    public string type {get;set;}
    public string target {get;set;}
    public string title {get;set;}
    public string link {get;set;}
}

Now i am trying to cast the objects, like this

List<Link> links = Model.relatedLinks.Select(l => new Link{type=l.type,target=l.target,title=l.title,link=l.link}).ToList();

Then i get the error

Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type

I found this page on how to cast anonymous objects, but im doing it the same way. Or have i missed something?

回答1:

If relatedLinks itself is a dynamic value, you've got two problems:

  • The lambda expression part as already reported
  • Extension methods can't be called on dynamic values (as extension methods). This affects both the Select and ToList methods.

You can work round the first by casting the lambda expression. You can work round the second by calling Enumerable.Select directly:

// Note: don't use var here. We need the implicit conversion from
// dynamic
IEnumerable<Link> query = Enumerable.Select(Model.relatedLinks, 
                              (Func<dynamic, Link>) (l => new Link { 
                                                            type = l.type,
                                                            target = l.target,
                                                            title = l.title,
                                                            link = l.link } );
var links = query.ToList();

Or for the sake of formatting:

Func<dynamic, Link> projection = l => new Link { 
                                        type = l.type,
                                        target = l.target,
                                        title = l.title,
                                        link = l.link };
IEnumerable<Link> query = Enumerable.Select(Model.relatedLinks, projection);
var links = query.ToList();

If Model.relatedLinks is already IEnumerable<dynamic> (or something similar) then you can call Select as an extension method instead - but you still need to have a strongly-typed delegate. So for example, the latter version would become:

Func<dynamic, Link> projection = l => new Link { 
                                        type = l.type,
                                        target = l.target,
                                        title = l.title,
                                        link = l.link };
IEnumerable<Link> query = Model.relatedLinks.Select(projection);
var links = query.ToList();