2012-02-24 7 views
0

以下のコードは、Listから継承するTのGenericクラスにあります。そのため、オブジェクトについて何もわからなくて、なぜ渡すのかメソッドの列名IQueryable.QueryProvider.CreateQuery例外:「引数式が無効です」

例外はメソッドのほとんどの行に表示されます。

public decimal? Max (string column) 
    { 
     IQueryable<T> queryableData = this.AsQueryable<T>(); 

     // Compose the expression tree that represents the parameter to the predicate. 
     ParameterExpression pe = Expression.Parameter(typeof(T), "item"); 

     // ***** Select(item => item.[column]) ***** 
     // Create an expression tree that represents the expression 'item.[column] == "id"' 
     Expression left = null; 
     try 
     { 
      left = Expression.Property(pe, typeof(T).GetProperty(column, System.Type.EmptyTypes)); 
     } 
     catch 
     { 
     } 

     // Create an expression tree that represents the expression 
     // 'queryableData.Select(item => item.[column]) ' 
     MethodCallExpression whereCallExpression = null; 
     try 
     { 
      whereCallExpression = Expression.Call(
       typeof(Queryable), 
       "Select", 
       new Type[] { queryableData.ElementType, typeof(int) }, 
       queryableData.Expression, 
       Expression.Lambda<Func<T, int>>(left, new ParameterExpression[] { pe })); 

     } 
     catch 
     { 
     } 
     IQueryable<T> results = null; 

      string lexpression = whereCallExpression.ToString(); 
      // Create an executable query from the expression tree. 

      //Exception at this line of Code: 
      results= queryableData.Provider.CreateQuery<T>(whereCallExpression); 

     return Convert.ToInt32(results.Max()); 
    } 

(すなわちwhereCallEWxpression)に渡された式は正しいように見えますが、この例外が来る続ける:「引数の式が有効ではありません」。私は本当に立ち往生しており、解決策を見つけることができませんでした。

また、誰かがこれを達成するためのより良い方法を知っている場合は、私が思うことができるすべてを教えてください。

おかげで、

ロベルト

編集: whereCallExpressionにcontructionは、おそらく間違っています。問題はそれを解決する方法です。それは本当に私が理解できない難しいビットです。

編集2: try catch catchブロックが削除されました - デバッグ目的でのみそこにありました。

+1

あなた 'try'..'catch'使用することは愚かなようだ:あなたは実際にはしないでください例外が発生しないようにします( 'results'が' null'になるため、以前に何かが失敗した場合は 'return'文に例外が発生します)。 – hvd

+0

hvd - それは戻りません。 CreateQueryを呼び出すと例外がスローされます。明らかにwhereCallExpressionの構築は間違っています。それは私には間違ってどのように明確ではない。 –

+0

@RobertoBoniniこれは幾分OTですが、簡潔にするためにキャッチブロックの内容を省略しない限り、彼の指摘はまだまだあります。 –

答えて

2

「これを達成するためのよりよい方法」に答えるには、マックスを計算している時点でTが何であるかを知っていると仮定すると、組み込まれたIEnumerable.Max()拡張メソッドを使用しないのはなぜですか?あなたがあなたの質問の始まりを言っているように見えるとして、あなたのクラスがList<T>から継承し、これは動作するはずと仮定:

var myClass = new YourClass<Person>(); // obviously this would have been initialized and filled elsewhere 
var maxAge = myClass.Max(p => p.Age); //Assuming Person has an Age property 

あなたが本当にあなたのクラスのこの内部が必要な場合は、あなたのクラスでこのような何かを行うことができます(未テストコード先):

public class myClass<T> : List<T> { 
    private readonly Func<T, decimal> _fieldGetter; 

    public myClass(Func<T, decimal> fieldGetter) { 
     _fieldGetter = fieldGetter; 
    } 

    // then your Max becomes: 
    public decimal? Max() { 
     return this.Max(i => _fieldGetter(i)); 
    } 
} 
+0

私はそうするだろう - しかし、私はTまたはそのプロパティが何であるか分からないので、ランタイムを実行するまで、特定のプロパティをターゲットにするためにラムダを書く方法がわかりません。 Tとプロパティがあります。 –

+0

ああ、あなたは 'typeof(myClass <>)。MakeGenericType(...)'なんかしていますか?通常は、私が投稿したコードがクラスの消費者から呼び出されることを期待しています。消費者がそのフィールドを解決する方法を知っていることを期待しています。 –

+0

多かれ少なかれ同じように行う別の方法を示すために編集されています。 –

0

解決済み!右のトラックに私を置くためのクリスShainへ

答えは右の私の前にいた...おかげ

var result =this.Select(c => c.GetType().GetProperty(column).GetValue(c, null)); 

return (int)result.Max(); 
+0

これは、元の問題を実際に解決するものではありません。しかし、仕事を終わらせる。しかし、元の問題への解決策を得ることは興味深いでしょう。 –

関連する問題