6

データベースからさまざまなデータを取得し、それを使用して要求された型のオブジェクトを構築することになっている、驚くほど醜いメソッドがあります。目標は、このメソッドを含むクラスから派生するクラスが比較的クリーンになるように、さまざまな醜さを 1 つの場所にまとめることです。

タイプがnull可能であっても、単一のオブジェクトを返すことになっている場合に問題はありません。

protected T getValue<T>(ParameterObject myParameterObject)
{
    var typeOfT = typeof (T);

    if (typeOfT == typeof(bool))
    {
        string val = this.getValue(myParameterObject);

        if (val == null)
            return default(T);

        bool rVal;
        if (!Boolean.TryParse(val, out rVal))
            return default(T);

        return changeType<T>(rVal);
    }

    if (typeOfT == typeof (double?))
    {
        string val = this.getValue(myParameterObject);

        if (val == null)
            return default(T);

        double rVal;
        if (!Double.TryParse(val, out rVal))
            return default(T);

        return changeType<T>(rVal);
    }

    [...]
}

public static T changeType<T>(object value)
{
    var t = typeof(T);
    if (!t.IsGenericType || t.GetGenericTypeDefinition() != typeof(Nullable<>))
        return (T)Convert.ChangeType(value, t);

    if (value == null)
        return default(T);

    t = Nullable.GetUnderlyingType(t);
    return (T)Convert.ChangeType(value, t);
}

残念ながら、目的の戻り値の型が IList で、List を返したい場合があります。

protected T getValue<T>(ParameterObject myParameterObject)
{
    var typeOfT = typeof (T);

    if (typeOfT.IsGenericType)
    {
        if (typeOfT.GetGenericTypeDefinition() == typeof (IList<>))
        {
            var genericArgumentType = typeOfT.GenericTypeArguments.FirstOrDefault();
            var baseType = typeof (List<>);
            var genericType = baseType.MakeGenericType(new[] {genericArgumentType});

            var rVal = Activator.CreateInstance(genericType);

            [code to populate the list] 

            return changeType<T>(rVal);
        }

    [...]
}

T のインスタンスではなくオブジェクトであるため、rVal を返すことはできません。しかし、私の changeType() 関数は失敗し、エラーが発生します。

System.InvalidCastException: オブジェクトは IConvertible を実装する必要があります。

したがって、戻り値の型が IList であるジェネリック メソッドがあり、List であるオブジェクトがありますが、それへの参照は Object 型です。関数から返すことができるようにキャストするにはどうすればよいですか?

4

1 に答える 1

1

オブジェクトが を実装していないreturn (T)Convert.ChangeType(value, t);ため、行が失敗しています。valueIConvertible

MSDN ドキュメントから

[...] 変換を成功させるには、value にIConvertibleインターフェイスを実装する必要があります。これは、メソッドが適切なIConvertibleメソッドへの呼び出しをラップするだけだからです。このメソッドでは、value から conversionType への変換がサポートされている必要があります。

これを修正するには、一般的な方法はわかりませんがvalueIEnumerableorIEnumerable<>型であるという特定のケースでは、キャストしてからvalue.Select(x => changeType<ListGenT>(x))linq クエリを実行できます。メソッドを再帰的に使用することで、changeTypeネストされたジェネリック型も処理する必要があります。

于 2015-12-30T22:34:18.380 に答える