2009-09-09 1 views
25

これは、リフレクションで値を変換する場合のフォローアップです。this question別の型に特定のタイプのオブジェクトを変換するには、次のように行うことができます。Convert.ChangeTypeが2つのタイプの間で動作するかどうかをテストしてください

object convertedValue = Convert.ChangeType(value, targetType); 

考えると2タイプのインスタンス(FromTypeとToType言う)、変換が成功するかどうかをテストする方法はありますか?

など。

public static class TypeExtensions 
{ 
    public static bool CanChangeType(this Type fromType, Type toType) 
    { 
     // what to put here? 
    } 
} 

EDIT:これは私が今持っているものです。最後に

ConvertTypes = new Type[] { 
     typeof(Empty), typeof(object), typeof(DBNull), typeof(bool), typeof(char), typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal), 
     typeof(DateTime), typeof(object), typeof(string) 
    }; 

、この方法:私は静的コンストラクタで、この発見リフレクタでメソッドConvert.ChangeTypeをチェック醜いが、私はまだ別の方法を見ていない...

bool CanChangeType(Type sourceType, Type targetType) 
{ 
    try 
    { 
    var instanceOfSourceType = Activator.CreateInstance(sourceType); 
    Convert.ChangeType(instanceOfSourceType, targetType); 
    return true; // OK, it can be converted 
    } 
    catch (Exception ex) 
    { 
    return false; 
    } 
+3

ええ、私はConvert.TryChangeTypeメソッドが好きでしょう... –

+0

@トーマス:それはいいですが、それは私がここに必要なものではありません。私はまだfromTypeのインスタンスを持っていません。ただタイプ自体です。 – jeroenh

+2

確かに確かめることができるのは、fromTypeが 'IConvertible'を実装していると思いますが、実際に成功した変換は保証されません。 – LukeH

答えて

28

私はちょうどこの同じ問題に直面していましたが、Reflectorを使用してChangeTypeのソースを調べました。 ChangeTypeは3つのケースで例外をスローします。

1. conversionType is null. 
2. value is null. 
3. value does not implement IConvertible 

これらの3つがチェックされた後、変換されることが保証されます。ですから、パフォーマンスを大幅に節約し、単にこれらの3つの事を自分でチェックすることで試し{} /キャッチ{}ブロックを削除することができます

public static bool CanChangeType(object value, Type conversionType) 
{ 
    if (conversionType == null) 
    { 
     return false; 
    } 

    if (value == null) 
    {    
     return false; 
    } 

    IConvertible convertible = value as IConvertible; 

    if (convertible == null) 
    { 
     return false; 
    } 

    return true; 
} 
すでに私はこの思い付いた両方の質問に回答されているものに基づいて
+0

すばらしい答え。それについて自分自身を考えなければならないのですか?ありがとう。 – jeroenh

+0

ありがとう。私はちょっとしたチェックを省いたが、それはあなた次第である。 convertible == nullの場合、valueはすでに変換しようとしている型の値ですが、trueを返すことができます。 – esac

+26

InvalidCastExceptionがスローされることがあることに注意してください。そして、あなたはこれを事前チェックするために何もできないようです。 IConvertibleがCanConvertToTypeメソッドを持っていればいいでしょう。 – ctusch

8

ソースがIConvertibleを実装しているかどうか、またはターゲットが上記のConvertTypesのいずれかであるかどうかをチェックするだけです。私はSystem.Convertクラス以上のものを行うことができます変換クラスが含まれて少しのフレームワークを書かれている

return (ConvertTypes.Contains(toType) || typeof(IConvertible).IsAssignableFrom(fromType)); 
+4

上記のコメントと同様です。残念ながら、 'Type'が' IConvertible'を実装していることを確認するだけでは不十分です。試行されたコンバージョンが実際に成功するという保証はありません。 – LukeH

+0

私のシナリオでは、私はこれらの特別なプリミティブを心配しています。私は実際に 'ChangeType'を試してみるのがいいと試してみたいと思います。これは' try {...} catch {} '以外の唯一の合理的な方法です) –

+1

代わりに' HashSet 'を使うのが良いでしょう'Type []'の 'O(N)'検索を避けるためには、タイトなループでこのチェックを打つことが予想される場合、これはもっと重要です。 'BinarySearch()'を呼び出すこともオプションかもしれません –

0

:だからあなたのメソッドは、この(非常に粗い)のようになるはずです。使用に興味がある場合は、CodePlexからダウンロードできます。値の間で変換できるかどうかを判断する能力はありませんが、それは追加するには良い機能のようです。

それはに基づいて値を変換する機能が含まれてい:

  • IConvertible
  • TypeConverters
  • ToXxx方法
  • 解析静的メソッド
  • パラメータ化されたコンストラクタ
  • およびその他のいくつかのマイナーなもの

Data Type Conversions

+0

面白そうです。確かめます。 – jeroenh

0

public Item() 
    { 
     foreach (var pinfo in GetType().GetProperties()) 
     { 
      object value = 0; 
      var response = ReflectionHelpers.TryChangeType(value, pinfo.PropertyType); 
      if(response.IsSuccess) 
      { 
       pinfo.SetValue(this, response.Value); 
      } 
     } 
    } 

これは0で可能なすべてのプロパティを開始する:

public static object ChangeType(object value, Type conversion) 
    { 
     var type = conversion; 

     if (type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) 
     { 
      if (value == null) 
      { 
       return null; 
      } 

      type = Nullable.GetUnderlyingType(type); 
     } 

     return Convert.ChangeType(value, type); 
    } 

public static (bool IsSuccess, object Value) TryChangeType(object value, Type conversionType) 
    { 
     (bool IsSuccess, object Value) response = (false, null); 
     var isNotConvertible = 
      conversionType == null 
       || value == null 
       || !(value is IConvertible) 
      || !(value.GetType() == conversionType); 
     if (isNotConvertible) 
     { 
      return response; 
     } 
     try 
     { 
      response = (true, ChangeType(value, conversionType)); 
     } 
     catch (Exception) 
     { 
      response.Value = null; 
     } 

     return response; 
    } 
} 

製造コード例(C#7が必要)。

関連する問題