C # linq - Cambiar el campo seleccionado en tiempo de ejecución

c# dynamic expression-trees linq

Pregunta

Tengo un objeto Pedidos (Pedido, Producto, Costo, Precio, Cliente, Día). Estoy recuperando una gran cantidad de registros de la base de datos y para facilitar el filtrado, necesito rellenar DropDownLists con los distintos valores recuperados para que el usuario pueda seleccionar solo fechas específicas o productos específicos o incluso un precio específico. Los ID de DropDownList se crean como "ddl_" + nombre del campo en cuestión.

Lo que me gustaría es poder definir una matriz simple como esta:

public string[] filterArray = new string[] { "Order", "Product", "Cost", "Price", "Client", "Day" };

Entonces llama a un método BindDLLs:

foreach (string filterName in filterArray)
{
    // Find the ddl to populate
    DropDownList ddl = (DropDownList)this.FindControl("ddl_" + filterName);
    // Get the data for that ddl only (use filterName in the select...)
    var query = (from items in results select items.filterName.ToString()).Distinct();

    // Populate the ddl (not complete code...)
    foreach (var item in query)
    {
        ddl.Items.Add(item...);
    }
}

Mi problema es que encuentro mucha documentación sobre cómo modificar las instrucciones WHERE o GROUP BY o cualquier otra parte de linq en tiempo de ejecución. Simplemente no encuentro ninguno sobre cómo cambiar dinámicamente el campo que quiero recuperar.

¿Hay una forma fácil de hacer esto? Gracias. Yipi

Editar:

List<Orders> results = OrdersService.GetOrders();

public class Orders
{
    [DataMember]
    public DateTime? Day
    [DataMember]
    public int? Order
    [DataMember]
    public int? Product
    [DataMember]
    public int? Cost
    [DataMember]
    public int? Price
    [DataMember]
    public int? Client
    [DataMember]
}

Respuesta popular

Puedes resolver este problema construyendo la expresión lambda a mano.

La consulta que utiliza actualmente se puede cambiar para usar la sintaxis de las cadenas de métodos y luego se verá así:

var query = results.Select(item => item.<filterName>.ToString()).Distinct();

Ahora necesitamos crear la expresión lambda que se pasa a Distinct nosotros mismos.

Esto se puede lograr utilizando el siguiente método:

Expression<Func<YourResultType, string>> CreateExpression(string propertyName)
{
    var itemExpression = Expression.Parameter(typeof(YourResultType), "item");
    var propertyExpression = Expression.Property(itemExpression, propertyName);
    var toStringExpression = Expression.Call(propertyExpression,
                                             "ToString", null);
    return Expression.Lambda<Func<YourResultType, string>>(toStringExpression, 
                                                           itemExpression);
}

Ahora podemos cambiar la consulta a esto:

var query = results.Select(CreateExpression(filterName)).Distinct();

Tenga en cuenta que debe cambiar YourResultType al tipo de instancias en su variable de results . Además, si no está consultando una base de datos sino una lista en la memoria, debe cambiar la consulta a esto:

var query = results.Select(CreateExpression(filterName).Compile()).Distinct();


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow