2012-03-11 11 views
1

私はユーザー入力からいくつかの解析を行います。ここでは、特定の型の引数の配列を解析する必要があります。LINQ式異なるオブジェクト型を持つ配列を作成する

構文解析の時点では、それぞれの引数をどのタイプにするか分かりませんが、どのタイプにも評価できます。だから、私は一時的にオブジェクトの配列に格納することにしました。私はこのような何かしようとすると、しかし:

NewArrayExpression returnValue = Expression.NewArrayInit(typeof(object), expressionList); 

を私は次の例外を取得:タイプの表現「を可能System.Int32」タイプの配列を初期化するために使用することはできません「のSystem.Object」。

暗黙のボクシングが起こっていないので、つまり、私は仮定しています。だから私はそれ自身ボックス:

expressionList.Add(Expression.TypeAs(expression, typeof(object))); or 
expressionList.Add(Expression.Convert(expression, typeof(object))); 

これまでのところとても良い:私は配列内のさまざまな種類のオブジェクトのリストを得た。これは

Expression.Convert(expr, typeof(int)); or 
Expression.Unbox(expr, typeof(int)); 

しかし、私は最終的に所望の種類を得るとき、私はそのタイプに上位配列の値のすべてを変換してみてください、私はそれを変換(その型がint usualyていると言うことができます) exprがactualy文字列「AAAAA」であるとき、両方のコマンドのデバッグビューは:

(System.Int32)((System.Object)"aaaaa") 

さて、ここで私の問題がある:これは例外をスローしません。しかし、それは最終的に表現がコンパイルされる時になります。つまり、文字列はintではありません。

これは本当に例外を投げるべきではないかもしれませんが、わかりません。しかし、これは私のためには機能しません。

これに対して治療法はありますか?

EDIT:のコードは次のようになります。

static Expression InArguments(ParameterExpression pe, string[] arguments) 
{ 
    List<Expression> listaExpr = new List<Expression>(); 
    foreach (string s in arguments) 
    { 
     Expression expression = Complete(pe, s); // evaluate argument 
     // listaExpr.Add(Expression.Convert(expression, typeof(object))); 
    } 
    return Expression.NewArrayInit(typeof(object), listaExpr); 
} 
+0

は、なぜあなたは、配列内のオブジェクトを格納する必要があると思いますか?式全体のサンプルを表示できますか?特に配列の使い方は? – svick

+0

さて、私はSQL IN演算子を模倣しようとしています。ユーザーは のようなコードを入力する必要があります。Item.Code IN [1,2,3]またはPartner.Name IN ["aa"、 "bb"] Codeは動的にintに評価され、Nameはstringに評価されます。 また、これは許可されています:Item.Code IN [1,2、Partner.GetTopItem()] –

+0

したがって、単純な型(int、string、decimal)になる可能性のあるIN演算子のすべての引数を評価する必要があります。私のモデルからのどんなタイプでも、またはその事柄についてはそれらのコレクションをもたらす可能性があります。その後、私はそれらを左のオペランドの型にキャストします。私は知らない、多分私はものをovercomplicatingしている –

答えて

2

あなたがタイプを知っているように私には思える、あなたが遅すぎるそれを計算することだけです。あなたがそれを変えることができれば、それはあなたの問題を解決するだろう。この方法は、次のようになります。

static Expression InArguments(
    ParameterExpression pe, string[] arguments, Type itemType) 
{ 
    List<Expression> listaExpr = new List<Expression>(); 
    foreach (string s in arguments) 
    { 
     Expression expression = Complete(pe, s, itemType); // evaluate argument 
     listaExpr.Add(expression, typeof(object)); 
    } 
    return Expression.NewArrayInit(itemType, listaExpr); 
} 

そして、それはこのようなものになります呼び出すコード:それは私の問題だった、

Expression inProperty = InProperty(…); 
Expression inArguments = InArguments(pe, arguments, inProperty.Type); 

Expression result = Expression.Call(containsMethod, inArguments, inProperty); 
0

@svick

うんを。私のシステム全体は、左右のオペランドを独立に解決し、それらの間の変換可能性をチェックするように設定されていました。それで、私はIN演算子の右オペランドがオブジェクト配列の式を返すようにしました。変換可能なオブジェクトのそれぞれをテストすることができましたが、オブジェクトに変換すると、何かに変換可能ですか? 。

static Expression InArguments(ParameterExpression pe, string arguments) 
    { 
     string substr = arguments.Substring(1, arguments.Length - 2); 
     string[] arr = substr.Split(','); 
     return Expression.Constant(arr, typeof(string[])); 
    } 

そして、後:私は私が実際に参照できるポイントに私の引数をforwared

static Expression InOperator(Expression left, Expression right, ParameterExpression pe) 
    { 
     Expression finalexpr = null; 

     // this solved my problem. 
     string[] args = Expression.Lambda<Func<string[]>>(right).Compile()(); 

     foreach (string s in args) 
     { 
      Expression converted = null;     

      try 
      { 
       Expression expr = Complete(pe, s); 
       converted = Expression.Convert(expr, (left as Expression).Type); 
      } 
      catch 
      { 
       throw; 
      } 

      if (finalexpr == null) finalexpr = Expression.Constant(false); 
      finalexpr = Expression.OrElse(finalexpr, Expression.Equal(left, converted)); 
     } 

     return finalexpr; 
    } 

だから、私は私の右オペランドからの発現後返すようにすることを決めました左のオペランドタイプをstring []の定数式の中に入れてコンパイルして、文字列引数を戻します。

しかし、私は、オブジェクト配列でそれを転送することができればまだ、私が好きだろうが...

関連する問題