4

私はかなりトリッキーな問題に取り組んでいます。非常に高いレベルでは、プリミティブであるオブジェクトがあり、C# で別のプリミティブ型に強制する必要があります。値と型は実行時に決定されます。

私は大まかにこれを試しました(私のコードはより複雑です、これは問題を示しています):

object value = (int)0x8ba9dc90;
Type t = typeof(UInt64);
object result = Convert.ChangeType(value, t);

これは、(上記のように) オーバーフローまたはアンダーフローが発生する場合を除いて、時々機能します。

私が望んでいるのは、(変換ではなく)強制が発生することです。この場合、単純に「(int)0x8ba9dc90」を「(ulong)0x8ba9dc90」にしたいと思います。float と同様: value = "(float)-32.01" で "t" が "UInt64" の場合、結果を "0xffffffffffffffe0" にしたい。「unchecked { ulong u = (ulong)(double)-32.01; }」を実行すると、まさにこれが得られます。

これを行う方法はありますか、またはカスタムコンバーターの作成に行き詰まっていますか?

(はい、これを行うのは奇妙なことだと認識しています。これはすべて非常に動的なコードであり、DynamicObject.TryConvert オーバーライドで強制を実行しようとしています。また、多くの場合、これが行われることを十分に認識しています。ダウン キャストなどを介してデータを破棄します。これは、私のアプリケーションではまったく問題ありません。巨大な入れ子になった switch ステートメントがなければ、これを記述する方法がわかりません。)

編集:明確にするために、私の関数は次のようになります:

public override bool TryConvert(ConvertBinder binder, out object result)
{
    if (binder.Type.IsPrimitive && m_type.IsPrimitive)
    {
        // m_type is System.Type, which is m_value's current type.
        // m_value is System.Object, contains a primitive value.
        // binder.Type is the System.Type I need to coerce m_value into.
        result = Convert.ChangeType(m_value, binder.Type);
        return true;
    }
    result = null;
    return false;
}
4

1 に答える 1

4

LINQ 式を使用して、この変換を行うことができます。この記事では、その方法について説明します。

基本的な考え方は、キャスト式と同等の LINQ 式を構築することです。

ParameterExpression convParameter = Expression.Parameter(typeof(object), "val");
var conv = (Func<object,object>)Expression.Lambda(
    Expression.Convert(
        Expression.Convert(
            Expression.Convert(
                convParameter
            ,   fromType
            )
        ,   targetType
        )
    ,   typeof(object)
    )
    ,   convParameter
).Compile();

これで、元の型の値をラップして呼び出しconvて渡すことができます。object強制された値が返されます。このコードは、カスタムの型変換も取得します (プリミティブではなく、独自の型に対して)。必要に応じて、オブジェクトのネストのレベルを上げることで、間にさらに変換を追加できExpression.Convertます。

于 2012-09-09T01:55:52.617 に答える