0

J'essaie de créer une fonction générique pour appliquer des règles sur DataRows.Variable '' de type 'System.Data.DataRow' référencé à partir de la portée '', mais il n'est pas défini

Mais je reçois l'erreur suivante lors de l'exécution du programe

Voici mon code.

public Func<T, bool> CompileRuleDataRow<T>(Rule r) 
{ 
    var paramUser = Expression.Parameter(typeof(T)); 
    Expression expr = BuildExprDataRow<T>(r, paramUser); 
    // build a lambda function User->bool and compile it 
    //Expression.Lambda<Func<T, bool>>(
    return Expression.Lambda<Func<T, bool>>(expr, paramUser).Compile(); 
} 

Fonction d'expression de construction.

public Expression BuildExprDataRow<T>(Rule r, ParameterExpression param) 
{ 
    ParameterExpression objExpr = Expression.Parameter(typeof(string)); 
    string defaultMember = "Item"; 
    ConstantExpression indexExpr = Expression.Constant(r.MemberName); 
    Expression leftIndexAccessExpr = Expression.Property(objExpr, defaultMember, indexExpr); 
    ExpressionType tBinary; 
    // is the operator a known .NET operator? 
    ExpressionType.TryParse(r.Operator, out tBinary); 
    var right = Expression.Constant(r.TargetValue); 
    // use a binary operation, e.g. 'Equal' -> 'u.Age == 15' 
    return Expression.MakeBinary(tBinary, leftIndexAccessExpr, right); 
} 

et je l'appelle de cette façon dans la méthode principale.

var rule = new Rule("Name", "Equal", "3"); 
Func<DataRow, bool> compiledRuleDataRow = CompileRuleDataRow<DataRow>(rule); 
DataTable dt = new DataTable(); 
dt.Columns.Add("Id"); 
dt.Columns.Add("Name"); 
dt.Columns.Add("Address"); 
for (int i = 0; i < 100000; i++) 
{ 
    dt.Rows.Add(i.ToString(), i.ToString(), i.ToString()); 
} 
//I want to do something like this. 
    DataRow[] drFiltered = dt.Select().Where(r => compiledRuleDataRow(r)).ToArray(); 

Et ci-dessous est ma Rule classe

public class Rule 
{ 
    public string MemberName { get; set; } 
    public string Operator { get; set; } 
    public string TargetValue { get; set; } 

    public Rule(string MemberName, string Operator, string TargetValue) 
    { 
    this.MemberName = MemberName; 
    this.Operator = Operator; 
    this.TargetValue = TargetValue; 
    } 
} 

Quand je lance ce code, je reçois l'erreur suivante.

variable '' of type 'System.Data.DataRow' referenced from scope '', but it is not defined

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: variable '' of type 'System.Data.DataRow' referenced from scope '', but it is not defined

Quelqu'un peut-il m'aider s'il vous plaît?

+0

Lorsque j'exécute votre code, j'obtiens une erreur différente: "Propriété d'instance" Item (String) 'n'est pas défini pour le type' System.String '". Et je ne comprends pas ce que ce code tente de faire (il essaie de faire quelque chose comme 's [" Name "]', pour une chaîne non définie 's', ce qui n'a aucun sens pour moi), donc je Je ne sais pas comment le réparer. – svick

Répondre

1

Comme @svick, j'obtiens une erreur différente du code affiché.

De toute façon, il y a deux problèmes avec cette méthode BuildExprDataRow. Tout d'abord, il n'utilise pas l'argument param transmis. Deuxièmement, la valeur de la propriété n'est pas correctement convertie, donc les opérateurs binaires ne fonctionnent pas.

Voici la méthode fixe:

public Expression BuildExprDataRow<T>(Rule r, ParameterExpression param) 
{ 
    var right = Expression.Constant(r.TargetValue); 
    var left = Expression.Convert(
     Expression.Property(param, "Item", Expression.Constant(r.MemberName)), 
     right.Type); 
    var comparison = (ExpressionType)Enum.Parse(typeof(ExpressionType), r.Operator); 
    return Expression.MakeBinary(comparison, left, right); 
} 

BTW, l'argument générique T n'est pas utilisé à l'intérieur de cette méthode et vous pouvez le supprimer (faire la méthode non générique).