2015-12-30 16 views
5

私はデータベースからさまざまなデータを引き出し、要求されたタイプのオブジェクトを構築するために使用される驚くほど醜いメソッドを持っています。目的は、揃った醜さを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のである場合がありますそれはオブジェクトではなく、Tのインスタンスです。しかし、私のchangeType実行()関数がエラーで、失敗しているので、私はRVALを返すことができません

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

    [...] 
} 

System.InvalidCastException: Object must implement IConvertible.

私はリストを返すようにしたいです

戻り値の型がIListの汎用メソッドがあり、オブジェクトはListですが、その参照はObject型です。どのように私はそれを関数から返すことができるようにキャストするのですか?

+2

私は明白な何かを見逃していますが、なぜreturn(T)(object)rVal;の代わりにreturn changeType (rVal); – 31eee384

答えて

1

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

[...] For the conversion to succeed, value must implement the IConvertible interface, because the method simply wraps a call to an appropriate IConvertible method. The method requires that conversion of value to conversionType be supported.

は、この問題を解決するには

から、私は一般的な方法のかわからないけどIEnumerableまたはIEnumerable<>タイプのvalueビーイングの特定の場合のために、あなたが行うその後、キャストしようとすることができvalue.Select(x => changeType<ListGenT>(x)) linqクエリ。 changeTypeメソッドを再帰的に使用することで、ネストされたジェネリック型も処理する必要があります。

+0

私はまだ分かりませんが、リストを返すようにメソッドを変更した場合、リストを作成してIList を返す代わりに、問題は解決しました。 –