Dynamic + linq compilation error
I'll say up front that I am doing some really scary things with linq on dynamic data. But I can't figure out why this query fails to compile:
Error 1 The property '<>h__TransparentIdentifier0' cannot be used with type arguments
public class Program { public static void Main(string[] args) { var docs = new dynamic[0]; var q = from doc in docs where doc["@metadata"]["Raven-Entity-Name"] == "Cases" where doc.AssociatedEntities != null from entity in doc.AssociatedEntities where entity.Tags != null // COMPILER ERROR HERE from tag in entity.Tags where tag.ReferencedAggregate != null select new {tag.ReferencedAggregate.Id, doc.__document_id}; } } public static class LinqOnDynamic { private static IEnumerable<dynamic> Select(this object self) { if (self == null) yield break; if (self is IEnumerable == false || self is string) throw new InvalidOperationException("Attempted to enumerate over " + self.GetType().Name); foreach (var item in ((IEnumerable) self)) { yield return item; } } public static IEnumerable<dynamic> SelectMany(this object source, Func<dynamic, int, IEnumerable<dynamic>> collectionSelector, Func<dynamic, dynamic, dynamic> resultSelector) { return Enumerable.SelectMany(Select(source), collectionSelector, resultSelector); } public static IEnumerable<dynamic> SelectMany(this object source, Func<dynamic, IEnumerable<dynamic>> collectionSelector, Func<dynamic, dynamic, dynamic> resultSelector) { return Enumerable.SelectMany(Select(source), collectionSelector, resultSelector); } public static IEnumerable<dynamic> SelectMany(this object source, Func<object, IEnumerable<dynamic>> selector) { return Select(source).SelectMany<object, object>(selector); } public static IEnumerable<dynamic> SelectMany(this object source, Func<object, int, IEnumerable<dynamic>> selector) { return Select(source).SelectMany<object, object>(selector); } }
To add insult to injury, the following works:
var docs = new dynamic[0]; var q = from doc in docs where doc["@metadata"]["Raven-Entity-Name"] == "Cases" where doc.AssociatedEntities != null from entity in doc.AssociatedEntities where entity.Tags != null from tag in entity.Tags select new { tag.ReferencedAggregate.Id, doc.__document_id };
It is only when I add:
where tag.ReferencedAggregate != null
That I get an error two lines before:
where entity.Tags != null // COMPILER ERROR HERE
Not sure what is going on
If I try just converting your calls to:
var q = from doc in docs.Where(doc => doc["@metadata"]["Raven-Entity-Name"] == "Cases" || doc.AssociatedEntities != null)
from entity in doc.AssociatedEntities.Where(entity => entity.Tags != null)
I get a different compiler error which perhaps reveals what is going on:
'Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type'
So I guess you have to overload the Where operator.
var q = from doc in docs where doc["@metadata"]["Raven-Entity-Name"] == "Cases" where doc.AssociatedEntities != null from entity in ((IEnumerable<dynamic>)doc.AssociatedEntities) .Where(entity => entity.Tags != null) from tag in ((IEnumerable<dynamic>)entity.Tags) .Where(tag => tag.ReferencedAggregate != null) select new { tag.ReferencedAggregate.Id, doc.__document_id };
That's a little better. Not perfect, but it's like inception - you can only go so many levels deep before you get lost in limbo.
The Anonymous type return is <>h__TransparentIdentifier0 and is worked up by the compiler at compile-time - the problem appears to "dynamic order of precedence" - have a read here: Method-missing difficulties in C# 4.0: dynamic vs RealProxy
I just went through this today working up a recent post. I'll have a small guess and say that the Anonymous type is prepared after the dynamic assignment :) - the compiler knows this and is thwarting you.
Does the problem go away if you use a regular type return? I'm guess it must.
链接地址: http://www.djcxy.com/p/53760.html上一篇: 什么是使用LINQ to C#的最佳模式
下一篇: 动态+ linq编译错误