Créer une fonction dynamic à partir d’un object

J’ai un object de critères dans lequel je devais transformer chaque propriété en une fonction si la valeur n’est pas nulle.

public class TestClassCriteria { public bool? ColumnA { get; set; } public bool? ColumnB { get; set; } } 

C’est ce que j’ai jusqu’à présent, mais je suis à peu près sûr de ne pas définir le lambda correct. C’est ce que j’essaie de réaliser. funcs.Add(x => x.ColumnA == criteria.ColumnA) .

 var properties = criteria.GetType().GetProperties(); var funcs = new List<Func>(); foreach (var property in properties) { var propertyName = property.Name; funcs.Add(x => x.GetType().GetProperty(propertyName).Name == criteria.GetType().GetProperty(propertyName).Name); } 

Il ne plante pas ou ne provoque aucune erreur, il ne fonctionne tout simplement pas.

Toute aide que vous pouvez fournir serait grandement appréciée.

Voulez-vous quelque chose comme ça?

  static List> GetCriteriaFunctions() { var criteriaFunctions = new List>(); // searching for nullable properties of criteria var criteriaProperties = typeof(TCriteria) .GetProperties() .Where(p => p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)); foreach (var property in criteriaProperties) { // this is entity parameter var entityParameterExpression = Expression.Parameter(typeof(TEntity)); // this is criteria parameter var criteriaParameterExpression = Expression.Parameter(typeof(TCriteria)); // this is criteria property access: "criteria.SomeProperty" var criteriaPropertyExpression = Expression.Property(criteriaParameterExpression, property); // this is testing for equality between criteria property and entity property; // note, that criteria property should be converted first; // also, this code makes assumption, that entity and criteria properties have the same names var testingForEqualityExpression = Expression.Equal( Expression.Convert(criteriaPropertyExpression, property.PropertyType.GetGenericArguments()[0]), Expression.Property(entityParameterExpression, property.Name)); // criteria.SomeProperty == null ? true : ((EntityPropertyType)criteria.SomeProperty == entity.SomeProperty) var body = Expression.Condition( Expression.Equal(criteriaPropertyExpression, Expression.Constant(null)), Expression.Constant(true), testingForEqualityExpression); // let's compile lambda to method var criteriaFunction = Expression.Lambda>(body, entityParameterExpression, criteriaParameterExpression).Comstack(); criteriaFunctions.Add(criteriaFunction); } return criteriaFunctions; } 

Entité d’échantillon et critères d’échantillon:

 class CustomerCriteria { public int? Age { get; set; } public bool? IsNew { get; set; } } class Customer { public ssortingng Name { get; set; } public int Age { get; set; } public bool IsNew { get; set; } } 

Usage:

  var criteriaFunctions = GetCriteriaFunctions(); var customer1 = new Customer { Name = "John", Age = 35, IsNew = false }; var customer2 = new Customer { Name = "Mary", Age = 27, IsNew = true }; var criteria1 = new CustomerCriteria { Age = 35 }; var criteria2 = new CustomerCriteria { IsNew = true }; Console.WriteLine("Is match: {0}", criteriaFunctions.All(f => f(customer1, criteria1))); Console.WriteLine("Is match: {0}", criteriaFunctions.All(f => f(customer2, criteria1))); Console.WriteLine("Is match: {0}", criteriaFunctions.All(f => f(customer1, criteria2))); Console.WriteLine("Is match: {0}", criteriaFunctions.All(f => f(customer2, criteria2))); 

Au lieu de votre code dynamic, ce code utilise un access fortement typé. Vous pouvez donc mettre en cache la liste de critères pour chaque paire “Entité – Critères” et tester plus rapidement la correspondance d’instance.

Votre expression actuelle compare les noms de propriété, mais je pense que vous souhaitez comparer les valeurs de propriété:

 var funcs = new List>(); foreach (var property in criteria.GetType().GetProperties()) { funcs.Add(x => x.GetType().GetProperty(property.Name).GetValue(x, null) == property.GetValue(criteria, null)); } 

Cependant, êtes-vous sûr de devoir faire cela? Il y aurait probablement une meilleure façon de refactoriser votre code afin que vous n’ayez pas besoin d’utiliser la reflection pour comparer des propriétés qui portent le même nom sur deux objects non liés.