c# - dinamico - linq expression builder
Error de compilaciĆ³n de Dynamic+linq (3)
El tipo anónimo devuelto es <> h__TransparentIdentifier0 y está compilado por el compilador en tiempo de compilación; el problema parece ser "orden dinámico de precedencia"; lea aquí: Dificultades con el método que falta en C # 4.0: dinámico frente a RealProxy
Acabo de pasar por esto hoy trabajando en una publicación reciente. Haré una pequeña suposición y diré que el tipo Anónimo se prepara después de la asignación dinámica :): el compilador lo sabe y lo está frustrando.
¿El problema desaparece si utiliza un tipo de declaración regular? Supongo que debe ser.
Diré por adelantado que estoy haciendo algunas cosas realmente aterradoras con linq en datos dinámicos. Pero no puedo entender por qué esta consulta no se compila:
Error 1 La propiedad ''<> h__TransparentIdentifier0'' no puede usarse 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 agregar insulto a la lesión, los siguientes trabajos:
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 solo cuando agrego:
donde tag.ReferencedAggregate! = null
Que me sale un error dos líneas antes:
donde entidad.Etiquetas! = nulo // ERROR COMPILADOR AQUÍ
No estoy seguro de lo que está pasando
Si 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)
Recibo un error de compilador diferente que tal vez revela lo que está pasando:
''No se puede usar una expresión lambda como un argumento para una operación distribuida dinámicamente sin antes convertirla en un tipo de árbol de expresión o delegado''
Así que supongo que hay que sobrecargar al operador Where.
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 está un poco mejor. No es perfecto, pero es como un comienzo: solo puedes llegar a tantos niveles de profundidad antes de perderte en el limbo.