c# - new - Crear una expresión genérica a partir del nombre de la propiedad de cadena
generic parameter c# (1)
Necesitas usar la sobrecarga genérica correcta, lo que solía significar que tenías que usar MakeGenericMethod
; sin embargo, también puede usar la dynamic
para evitar la necesidad de usar MakeGenericMethod
aquí, por ejemplo (en este caso a través de Where
, pero el punto importante es cómo funciona):
IQueryable<Foo> source = new[] { new Foo { Bar = 123 } }.AsQueryable();
Expression<Func<Foo,bool>> typed = x=>x.Bar == 123;
LambdaExpression untyped = typed;
IQueryable<Foo> filtered = Queryable.Where(source, (dynamic)untyped);
Nota: aquí no puede usar los métodos de extensión , por lo que necesita usar Queryable.*
.
Para un ejemplo de OrderBy
usando tu código:
var parameter = Expression.Parameter(typeof(Foo));
var memberExpression = Expression.Property(parameter, "Bar");
var lambdaExpression = Expression.Lambda(memberExpression, parameter);
LambdaExpression untyped = lambdaExpression;
IQueryable<Foo> sorted = Queryable.OrderBy(source, (dynamic)untyped);
var all = sorted.ToArray();
Re la edición:
var parameter = Expression.Parameter(typeof(IRelationship));
var memberExpression = Expression.Property(
Expression.Convert(parameter, typeof(IContract)), data.SortColumn);
var orderBy = Expression.Lambda(memberExpression, parameter);
Tengo una variable llamada sortColumn, que contiene el texto de una columna por la que quiero ordenar el resultado de una consulta. También tengo un repositorio genérico que toma como parámetro una expresión que contiene el campo por el que quiero ordenar. Parece que no puedo pasar del nombre de la propiedad de cadena a una expresión.
Así que el repositorio genérico que tengo contiene el siguiente método
public IEnumerable<TEntity> Get<TOrderBy>(Expression<Func<TEntity, bool>> criteria,
Expression<Func<TEntity, TOrderBy>> orderBy, int pageIndex,
int pageSize,
bool isAssendingOrder = true,
EnumDeletePolicy deletePolicy = EnumDeletePolicy.ExcludeDeleted)
Note que el segundo parámetro de este Get es Expression-Func-TEntity, TOrderBy. Como mencioné, tengo una variable llamada sortColumn, que contiene la cadena de una propiedad en mi objeto de identidad. Necesito convertir esta cadena en una expresión que pueda pasar al método Get.
Aquí está lo que tengo ahora mismo.
var parameter = Expression.Parameter(typeof(IContract));
var memberExpression = Expression.Property(parameter, data.SortColumn);
var lambdaExpression = Expression.Lambda(memberExpression, parameter);
Que crea un objeto de tipo LambdaExpression. El tipo real de esta LambdaExpression es una expresión-Func-IContract, cadena (o cualquiera que sea el tipo sortColumn de la propiedad). Si llamo al método Get y paso en esta LambdaExpression y lo convierto explícitamente al tipo de expresión, entonces funcionará bien. El problema es que no sé cuál es el tipo de expresión, podría ser una cadena, int, int ?, etc. Todo depende del tipo de propiedad que sea específico en la propiedad sortColumn.
¿Puedes ayudarme a hacer este último salto al tipo de expresión correcto?
Edición basada en las sugerencias de Marc: Casi tengo este trabajo, en realidad basado específicamente en la pregunta que está funcionando, pero tengo un problema pendiente.
El IContract que es el tipo de entidad contra el que estoy consultando en realidad hereda de IRelationship. Si especifico un campo desde la interfaz de IContract, entonces el código anterior funciona. Si especifico un campo de la interfaz de IRelationship, la siguiente línea falla.
var memberExpression = Expression.Property(parameter, data.SortColumn);
Si intento algo como a continuación para obtener la expresión Member de la relación de relaciones, pero al crear Lambda en base a IContract obtengo un error del repositorio.
var parameter = Expression.Parameter(typeof(IRelationship));
var memberExpression = Expression.Property(parameter, data.SortColumn);
var orderBy = Expression.Lambda(memberExpression, Expression.Parameter(typeof(IContract)));
El error que recibo es "El parámetro '''' no estaba vinculado en la expresión de consulta LINQ a Entidades especificada".
La última expresión para que funcione sea esta.
var parameter = Expression.Parameter(typeof(IContract));
var memberExpression = Expression.Property(parameter, typeof(IRelationship), data.SortColumn);
var orderBy = Expression.Lambda(memberExpression, parameter);
Así que necesitaba especificar el parámetro medio de la línea memberExpression, para decir, buscar en la interfaz de relaciones heredada para la propiedad