2010-08-09 7 views
18

Diré desde el principio que estoy haciendo cosas realmente aterradoras con linq en datos dinámicos. pero no puedo entender por qué esta consulta falla al compilar:Error de compilación dinámico + linq

de error 1 La propiedad '<> h__TransparentIdentifier0' no se puede usar con argumentos de tipo

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

    } 
} 

Para colmo de males, las siguientes obras :

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

es sólo cuando agrego:

donde tag.ReferencedAggregate = null

Eso me da un error de dos líneas antes:

donde entity.Tags = null // ERROR COMPILER AQUÍ

No está seguro de lo que está pasando

Respuesta

12

si lo intento simplemente convertir sus llamadas a:

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) 

me sale un error de compilación diferente, que quizá revela lo que está pasando:

'No se puede utilizar una expresión lambda como un argumento a una dinámicamente operación despachada sin enviarla primero a un árbol delegado o de expresión tipo '

Supongo que tiene que sobrecargar el operador Where.

+3

Gracias, eso fue todo. Terminé resolviendo esto usando: desde la etiqueta en entity.Tags.Where ((Func ) (t => t.ReferencedAggregate! = Null)) Feo como el infierno. Traté de escribir el método de extensión allí, pero no pude entender cómo hacer que CSC lo acepte. –

1

El tipo de retorno anónimo es <> h__TransparentIdentifier0 y se elabora por el compilador en tiempo de compilación - el problema parece "orden de precedencia dinámico" - Tiene una lectura aquí: Method-missing difficulties in C# 4.0: dynamic vs RealProxy

acabo de ir a través de este trabajo hasta hoy ar ecent post. Tendré una pequeña suposición y diré que el tipo Anónimo está preparado después de la asignación dinámica :) - el compilador lo sabe y lo está frustrando.

¿El problema desaparece si utiliza un retorno de tipo normal? Supongo que debe.

+0

Rob, No lo creo. El problema principal es que funciona para muchos otros escenarios. No puedo entender por qué no funciona para esto. Todos los métodos LinqOnDynamic devuelven IEnumerable de dinámico, por lo que no debería ser un problema. Parece que está intentando hacer un enlace fuerte a un método de extensión, pero no veo cómo. –

+0

Ahh - dynamic no admite ExtensionMethods: http://stackoverflow.com/questions/258988/will-the-dynamic-keyword-in-c4-support-extension-methods No puedo decir exactamente dónde lo estoy usando, pero yah Extension Methods podría ser el problema. –

+0

Esto no se está ejecutando en dinámico, se ejecuta en IEnumerable de dinámico Ese es un tipo estático, por lo que puede tener métodos de extensión. –

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

Eso es un poco mejor. No es perfecto, pero es como un principio: solo puedes llegar a muchos niveles antes de que te pierdas en el limbo.

Cuestiones relacionadas