2010-08-09 59 views
18

我會先說我正在做一些關於linq動態數據的非常可怕的事情。 但我不明白,爲什麼這個查詢失敗編譯:Dynamic + linq編譯錯誤

錯誤1酒店「<> h__TransparentIdentifier0」不能與類型參數一起使用

 
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); 

    } 
} 

要雪上加霜的是,以下的作品:

 
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 }; 

只有當我!地址:

其中tag.ReferencedAggregate = NULL

我得到一個錯誤的兩行之前:

其中entity.Tags = NULL //編譯器錯誤HERE

不知道什麼是對

回答

12

,如果我嘗試只是轉換你的來電:

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) 

我得到這或許揭示了是怎麼回事不同的編譯器錯誤:

「不能使用lambda表達式作爲參數傳遞給動態調度操作沒有首先將其轉換爲委託或表達式樹型'

所以我想你必須重載Where操作符。

+3

謝謝,就是這樣。 ((Func )(t => t.ReferencedAggregate!= null)) 醜陋如地獄。 我試圖在那裏寫擴展方法,但我無法弄清楚如何讓CSC接受它。 – 2010-08-10 01:09:00

1

打算匿名類型回報<> h__TransparentIdentifier0並在編譯時由編譯器進行處理 - 問題看起來像是「動態優先順序」 - 請看這裏: Method-missing difficulties in C# 4.0: dynamic vs RealProxy

我剛剛通過這個今天工作了ar ecent post。我會有一個小猜測,並說在匿名類型準備動態分配:) - 編譯器知道這一點,並阻止你。

如果您使用常規類型的退貨,問題是否消失?我猜是必須的。

+0

Rob, 我不這麼認爲。 主要問題是它適用於很多其他場景。 我不明白爲什麼它不適用於此。 所有的LinqOnDynamic方法都返回IEnumerable的動態,所以這應該不成問題。 看起來它試圖對擴展方法進行強綁定,但我看不出如何。 – 2010-08-09 23:05:59

+0

啊 - 動態不支持ExtensionMethods: http://stackoverflow.com/questions/258988/will-the-dynamic-keyword-in-c4-support-extension-methods 我不能確切地告訴你在哪裏'使用它 - 但是擴展方法可能是問題。 – 2010-08-09 23:33:18

+0

這實際上並不是在動態運行,它運行在動態IEnumerable上。 這是一個靜態類型,所以它可以有擴展方法。 – 2010-08-09 23:46:49

2
 
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 }; 

這稍微好一點。不完美,但它就像開始 - 在你陷入困境之前,你只能深入到很多層次。