C # Convirtiendo la cadena mágica en expresión lambda

Tengo un conjunto de métodos de extensión que permiten el uso de cadenas mágicas en el LINQ.OrderBy() metodos Sé que la primera pregunta será por qué, pero es parte de un repositorio genérico y ofrece flexibilidad para que las cadenas puedan enviarse desde la interfaz de usuario y usarse directamente.

Lo tengo funcionando si pasas una cadena mágica que representa una propiedad en la entidad principal que estás consultando, pero tengo problemas para hacerla más genérica, por lo que puede manejar múltiples niveles de cadena mágica profunda. Por ejemplo:

IQueryable<Contact> contacts = GetContacts();

contacts.OrderByProperty("Name"); // works great

// can't figure out how to handle this
contacts.OrderByProperty("ContactType.Name");

Aquí está el código que tengo hasta ahora:

public static class LinqHelpers
{
    private static readonly MethodInfo OrderByMethod = typeof(Queryable).GetMethods().Single(method => method.Name == "OrderBy" && method.GetParameters().Length == 2);
    private static readonly MethodInfo OrderByDescendingMethod = typeof(Queryable).GetMethods().Single(method => method.Name == "OrderByDescending" && method.GetParameters().Length == 2);
    private static readonly MethodInfo ThenByMethod = typeof(Queryable).GetMethods().Single(method => method.Name == "ThenBy" && method.GetParameters().Length == 2);
    private static readonly MethodInfo ThenByDescendingMethod = typeof(Queryable).GetMethods().Single(method => method.Name == "ThenByDescending" && method.GetParameters().Length == 2);

    public static IOrderedQueryable<TSource> ApplyOrdering<TSource>(IQueryable<TSource> source, string propertyName, MethodInfo orderingMethod)
    {
        var parameter = Expression.Parameter(typeof(TSource), "x");
        var orderByProperty = Expression.Property(parameter, propertyName);

        var lambda = Expression.Lambda(orderByProperty, new[] { parameter });

        var genericMethod = orderingMethod.MakeGenericMethod(new[] { typeof(TSource), orderByProperty.Type });

        return (IOrderedQueryable<TSource>)genericMethod.Invoke(null, new object[] { source, lambda });
    }

    public static IOrderedQueryable<TSource> OrderByProperty<TSource>(this IQueryable<TSource> source, string propertyName)
    {
        return ApplyOrdering(source, propertyName, OrderByMethod);
    }

    public static IOrderedQueryable<TSource> OrderByDescendingProperty<TSource>(this IQueryable<TSource> source, string propertyName)
    {
        return ApplyOrdering(source, propertyName, OrderByDescendingMethod);
    }

    public static IOrderedQueryable<TSource> ThenByProperty<TSource>(this IOrderedQueryable<TSource> source, string propertyName)
    {
        return ApplyOrdering(source, propertyName, ThenByMethod);
    }

    public static IOrderedQueryable<TSource> ThenByDescendingProperty<TSource>(this IOrderedQueryable<TSource> source, string propertyName)
    {
        return ApplyOrdering(source, propertyName, ThenByDescendingMethod);
    }
}

Estoy bastante seguro de que necesito dividir elpropertyName en el período y luego usar esas partes para construir una Expresión más complicada que involucra unaMemberExpression y luego una propiedad pero estoy luchando. Cualquier ayuda o apuntando en la dirección correcta sería apreciada.

Respuestas a la pregunta(1)

Su respuesta a la pregunta