J'ai regardé les autres versions de SO de cette question mais il semble que la sortie d'une méthode fonctionne pour d'autres. Je ne suis pas sûr de ce que je fais mal ici. Je suis nouveau à la partie du bâtiment d'expression de Linq.LambdaExpression à l'expression via les extensions Méthode
Ma méthode extensions est la suivante:
void Main()
{
var people = LoadData().AsQueryable();
var expression = people.PropertySelector<Person>("LastName");
expression.Should().BeOfType(typeof(Expression<Func<Person, object>>));
var result = people.OrderBy(expression);
}
public static class Extensions
{
public static Expression<Func<T, object>> PropertySelector<T>(this IEnumerable<T> collection, string propertyName)
{
if (string.IsNullOrWhiteSpace(propertyName))
{
throw new ArgumentException(nameof(propertyName));
}
var properties = typeof(T).GetProperties();
if (!properties.Any(p => p.Name == propertyName))
{
throw new ObjectNotFoundException($"Property: {propertyName} not found for type [{typeof(T).Name}]");
}
var propertyInfo = properties.Single(p => p.Name == propertyName);
var alias = Expression.Parameter(typeof(T), "_");
var property = Expression.Property(alias, propertyInfo);
var funcType = typeof(Func<,>).MakeGenericType(typeof(T), propertyInfo.PropertyType);
var lambda = Expression.Lambda(funcType, property, alias);
return (Expression<Func<T, object>>)lambda;
}
}
#region
private Random rand = new Random();
// Define other methods and classes here
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
public IEnumerable<Person> LoadData()
{
IList<Person> people = new List<Person>();
for (var i = 0; i < 15; i++)
{
people.Add(new Person
{
FirstName = $"FirstName {i}",
LastName = $"LastName {i}",
Age = rand.Next(1, 100)
});
}
return people;
}
#endregion
Je reçois une exception sur le rendement au cours de la distribution. À ce stade T
est de type Person
et object
est un string
. Mon lambda.GetType()
rapporte que c'est de type Expression<Func<Person, string>>
L'exception est:
Unable to cast object of type 'System.Linq.Expressions.Expression`1[System.Func`2[UserQuery+Person,System.String]]' to type 'System.Linq.Expressions.Expression`1[System.Func`2[UserQuery+Person,System.Object]]'.
Et mon casting est incorrect? Merci.
EDIT: J'ai mis à jour avec mon code complet avec lequel je joue en LinqPad. Je suis juste en train d'essayer de comprendre s'il existe un moyen facile de générer une expression lambda en transmettant le nom de la propriété. Je faisais quelque chose comme ça auparavant mais je faisais juste un changement de nom de propriété en utilisant ensuite la syntaxe lambda pour créer dynamiquement la requête OrderBy.
Ceci est strictement moi essayant d'apprendre comment les méthodes statiques d'expression peuvent être utilisées pour obtenir le même résultat que l'exemple ci-dessous. J'essaie d'imiter le ci-dessous via la méthode d'extension. Mais ça ne doit pas être comme ça. C'était plus facile d'essayer en plongeant dans LinqPad.
Expression<Func<Loan, object>> sortExpression;
switch (propertyFilter)
{
case "Age":
sortExpression = (l => l.Age);
break;
case "LastName":
sortExpression = (l => l.LastName);
break;
default:
sortExpression = (l => l.FirstName);
break;
}
var sortedLoans = loans.AsQueryable().OrderBy(sortExpression);
sortedLoans.Dump("Filtered Property Result");
Les classes sont invariantes. Donc, vous ne pouvez pas lancer l'expression à l'expression même si la conversion de TFunc1 en TFunc2 est autorisée. –
PetSerAl
Qu'essayez-vous d'accomplir avec cette méthode? J'essaie de comprendre pourquoi vous auriez besoin du Func. Essayez-vous de filtrer en fonction d'une propriété spécifique? –
bhmahler
Vous pouvez convertir un objet en objet via 'Expression.Convert (propriété, typeof (objet))'. –