Erreur: l'opérateur binaire Equal n'est pas défini pour les types 'System.Guid' et 'System.String'

c# entity-framework expression-trees

Question

C'est ma classe d'expression

        public static class ExpressionBuilder
    {
        private static MethodInfo containsMethod = typeof(string).GetMethod("Contains");
        private static MethodInfo startsWithMethod = typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) });
        private static MethodInfo endsWithMethod = typeof(string).GetMethod("EndsWith", new Type[] { typeof(string) });


        public static Expression<Func<T,
        bool>> GetExpression<T>(IList<Filter> filters)
        {
            if (filters.Count == 0)
                return null;

            ParameterExpression param = Expression.Parameter(typeof(T), "t");
            Expression exp = null;

            if (filters.Count == 1)
                exp = GetExpression<T>(param, filters[0]);
            else if (filters.Count == 2)
                exp = GetExpression<T>(param, filters[0], filters[1]);
            else
            {
                while (filters.Count > 0)
                {
                    var f1 = filters[0];
                    var f2 = filters[1];

                    if (exp == null)
                        exp = GetExpression<T>(param, filters[0], filters[1]);
                    else
                        exp = Expression.AndAlso(exp, GetExpression<T>(param, filters[0], filters[1]));

                    filters.Remove(f1);
                    filters.Remove(f2);

                    if (filters.Count == 1)
                    {
                        exp = Expression.AndAlso(exp, GetExpression<T>(param, filters[0]));
                        filters.RemoveAt(0);
                    }
                }
            }

            return Expression.Lambda<Func<T, bool>>(exp, param);
        }

        private static Expression GetExpression<T>(ParameterExpression param, Filter filter)
        {
            MemberExpression member = Expression.Property(param, filter.PropertyName);
            ConstantExpression constant = Expression.Constant(filter.Value);

            switch (filter.Operation)
            {
                case Op.Equals:
                    return Expression.Equal(member, Expression.Call(Expression.Convert(Expression.Constant(search.RetrieveGuid), typeof(object)), typeof(object).GetMethod("ToString"))), constant);

                case Op.GreaterThan:
                    return Expression.GreaterThan(member, constant);

                case Op.GreaterThanOrEqual:
                    return Expression.GreaterThanOrEqual(member, constant);

                case Op.LessThan:
                    return Expression.LessThan(member, constant);

                case Op.LessThanOrEqual:
                    return Expression.LessThanOrEqual(member, constant);

                case Op.Contains:
                    return Expression.Call(member, containsMethod, constant);

                case Op.StartsWith:
                    return Expression.Call(member, startsWithMethod, constant);

                case Op.EndsWith:
                    return Expression.Call(member, endsWithMethod, constant);
            }

            return null;
        }

        private static BinaryExpression GetExpression<T>
        (ParameterExpression param, Filter filter1, Filter filter2)
        {
            Expression bin1 = GetExpression<T>(param, filter1);
            Expression bin2 = GetExpression<T>(param, filter2);

            return Expression.AndAlso(bin1, bin2);
        }
    }

quand je génère une expression par ce code

 delegExpFilters = EntityExpression.ExpressionBuilder.GetExpression<Contact>(domainFilter).Compile();

my domainFilter Contient une liste d'enregistrements avec le nom du champ Propriété, l'opérateur et sa valeur. Mon champ est GUID.

quand j'appelle GetExpression, cela me donne une erreur L'opérateur binaire Equal n'est pas défini pour les types 'System.Guid' et 'System.String'

Réponse acceptée

Vous ne convertissez pas la valeur du filtre (chaîne) en un type approprié:

ConstantExpression constant = Expression.Constant(filter.Value);

Considérez que vous avez un filtre pour la propriété entière nommée Amount :

var filter = new Filter {
   PropertyName = "Amount",
   Operation = Op.GreaterThan,
   Value = "42"
};

Votre code générera une expression qui équivaut au code suivant

contract.Amount > "42"

Une telle comparaison d'entiers avec une chaîne n'est pas autorisée.


Vous devriez obtenir le type de propriété et convertir la valeur de filtre en ce type. Voici les étapes:

  1. Obtenir le convertisseur de type pour le type de propriété
  2. Vérifier s'il peut convertir une chaîne en type de propriété
  3. Est-ce que la conversion (qui retournera la valeur de la propriété en tant object
  4. Créer une expression cast pour convertir la valeur de la propriété d' object en type de propriété

Voici le code de la méthode GetExpression

var member = Expression.Property(param, filter.PropertyName);
var propertyType = ((PropertyInfo)member.Member).PropertyType;
var converter = TypeDescriptor.GetConverter(propertyType); // 1

if (!converter.CanConvertFrom(typeof(string))) // 2
   throw new NotSupportedException();

var propertyValue = converter.ConvertFromInvariantString(filter.Value); // 3
var constant = Expression.Constant(propertyValue);
var valueExpression = Expression.Convert(constant, propertyType); // 4

Vous devez utiliser cette expression de valeur à la place de votre expression constante dans les expressions binaires que vous renvoyez. Par exemple:

case Op.LessThan:
    return Expression.LessThan(member, valueExpression);
case Op.Equal:
    return Expression.Equal(member, valueExpression);
// etc

Pour l'égalité, vous devez également utiliser une expression binaire. Et maintenant, le filtre pour le Amount sera traduit en

 contract.Amount > (int)42


Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi