1

ユーザー入力からいくつかの解析を行っています。ここでは、特定のタイプである必要がある引数の配列を解析する必要があります。

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

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)));

これまでのところ、配列内のさまざまなタイプのオブジェクトのリストを取得しました。

しかし、最終的に目的のタイプを取得したら、すべての値を上の配列からそのタイプに変換しようとします (そのタイプは通常 int であるとしましょう)。

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

これは、expr が実際には文字列「aaaaa」である場合の両方のコマンドのデバッグ ビューです。

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

さて、ここに私の問題があります。これは例外をスローしません。しかし、expression が最終的にコンパイルされるときはそうなります。つまり、string は int ではありません。

たぶん、これは本当に例外をスローするべきではありません。わかりません。しかし、これは私にはうまくいきません。

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

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

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);
}
4

2 に答える 2

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);
于 2012-03-11T21:12:49.903 に答える
1

@スヴィック

ええ、それは私の問題でした。私のシステム全体は、左右のオペランドを個別に解決し、それらの間の変換可能性をチェックするようにセットアップされました。したがって、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[]));
    }

そして後で:

    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[] の定数式内で左オペランドの型を実際に参照できるようになるまで引数を控え、それをコンパイルして文字列引数を取得しました。

それでも、オブジェクト配列で転送できればよかったのですが...

于 2012-03-12T10:47:34.300 に答える