llegar a una propiedad profunda para una expresión lambda
Frecuentes
Visto 446 veces
0
Tengo algo de código así:
CaseHeaderComparer CaseComparer = new CaseHeaderComparer();
List<CaseHeader> CasesToProcess = new List<CaseHeader>();
foreach (GroupField fld in Fields)
{
//get the field property - ie. Division
System.Reflection.PropertyInfo piField = typeof(CaseHeader).GetProperty(fld.GroupFieldType.PropertyName);
//get the item property - ie. DivisionID
System.Reflection.PropertyInfo piItem = piField.PropertyType.GetProperty(fld.GroupFieldType.ValueMember);
foreach (CaseHeader ch in ToProcess)
{
object chItem = piField.GetValue(ch, null);
Guid ItemID = chItem != null ? (Guid)piItem.GetValue(chItem, null) : Guid.Empty;
if (fld.Items.Select(i => i.ItemID).Contains(ItemID))
{
CasesToProcess.Add(ch);
}
}
ToProcess = ToProcess.Except(CasesToProcess, CaseComparer).ToList();
}
A lo que me gustaría convertir para usar linq y lambdas. Me acerqué bastante con algo de ayuda de aquí ayer con esto:
List<CaseHeader> ToProcess = ....;
CaseHeaderComparer CaseComparer = new CaseHeaderComparer();
IEnumerable<CaseHeader> CasesToProcess = new BackingSheetCaseHeader[] { };
foreach (GroupField fld in Fields)
{
//get the field property - ie. Division
System.Reflection.PropertyInfo piField = typeof(CaseHeader).GetProperty(fld.GroupFieldType.PropertyName);
//get the item property - ie. DivisionID
System.Reflection.PropertyInfo piItem = piField.PropertyType.GetProperty(fld.GroupFieldType.ValueMember);
CasesToProcess.Union(
ToProcess
.Where(c => fld.Items.Select(i => i.ItemID)
.Contains((piField.GetValue(c, null) != null ? (Guid)piItem.GetValue(piField.GetValue(c, null), null) : Guid.Empty)))
, CaseComparer);
}
esto funciona, pero alguien señaló que podría hacer algo similar a esto ...
var hdr = typeof(CaseHeader);
var param = Expression.Parameter(hdr);
var cond = Expression.Condition(
Expression.NotEqual(param, Expression.Constant(null, hdr))
, Expression.Property(param, fld.GroupFieldType.PropertyName) <<-- but this needs to go 2 deep.. as above the item property..
, Expression.Constant(Guid.Empty)
);
var lambda = (Func<MyCaseObj,Guid>)Expression.Lambda(cond, param).Compile();
entonces podría hacer
var CasesToProcess = (from csh in CasesInGroup
where lambda(csh).In(fld.Items.Select(i => i.ItemID))
select csh);
pero el bit de profundidad 2 me está desconcertando como arriba. Necesito llegar a la propiedad fld.GroupFieldType.ValueMember de la propiedad fld.GroupFieldType.PropertyName del CaseHeader. el valor del primer nivel puede ser nulo..
¿Alguien puede darme algunos consejos, o algún lugar para leer sobre esto?
gracias
1 Respuestas
1
Puede ser que no necesites construir tu Expression
a mano en absoluto. El compilador de C# puede traducir expresiones lambda a Func<>
s y Expression<Func<>>
s. Tanto el siguiente trabajo:
var func = (Func<int, bool>)(i => i == 2);
var expression = (Expression<Func<int, bool>>)(i => i == 2);
después de lo cual expression.Compile()
es un Func<int,bool>
con el mismo comportamiento que func
! Así que intenta solo
var expression = (Expression<Func<MyCaseObj,Guid>>)
(c => fld.Items.Select(i => i.ItemID)
.Contains((piField.GetValue(c, null) != null
? (Guid)piItem.GetValue(piField.GetValue(c, null), null)
: Guid.Empty))
);
y tomarlo de ahí.
respondido 09 mar '12, 14:03
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas linq reflection lambda or haz tu propia pregunta.