2009-05-01 9 views
44

IEnumerable型のプロパティを持ち、LINQを使用してパラメータを操作したいクラス(Webコントロール)があります。IEnumerableをIEnumerableに変換する<T>

IEnumerableへのリフレクションによってキャスト/変換/呼び出しする方法はありますか<T>コンパイル時に型が分からないのですか?

おそらく IEnumerable.Cast<T>

このようにそれを使用する使用するようにコードをリファクタリングしたい

Method void (IEnumerable source) 
{ 
    var enumerator = source.GetEnumerator(); 

    if (enumerator.MoveNext()) 
    { 
     var type = enumerator.Current.GetType(); 
     Method2<type>(source); // this doesn't work! I know! 
    } 
} 

void Method2<T>(IEnumerable<T> source) {} 

答えて

56

あなたMethod2は本当にそれを取得どのような種類を気にしていましたか?ない場合は、あなただけのCast<object>()を呼び出すことができます。

void Method (IEnumerable source) 
{ 
    Method2(source.Cast<object>()); 
} 

あなたは間違いなく右のタイプを取得する必要がある場合は、リフレクションを使用する必要があります。それはソースが正確にIEnumerable<type>でないならば、呼び出しは失敗し、特に...しかし理想的ではないのです

MethodInfo method = typeof(MyType).GetMethod("Method2"); 
MethodInfo generic = method.MakeGenericMethod(type); 
generic.Invoke(this, new object[] {source}); 

:よう

何か。たとえば、最初の要素が文字列であるが、ソースがList<object>の場合、問題が発生します。

+0

状況に応じて、OfTypeを使用することもできます。以下も参照してください:http://stackoverflow.com/questions/4015930/when-to-use-cast-and-oftype-in​​-linq –

8

IEnumerable mySet = GetData(); 
var query = from x in mySet.Cast<int>() 
      where x > 2 
      select x; 
+0

:それは平野IEnumerableであるなら、あなたは、次の解決策のように、正しいIEnumerable<T>タイプに変換し、別の方法を作成する必要があります。同じ問題。 – andleer

+0

それは正しいです。方法2もそうです。 IEnumerable にいつでもキャストすることができます... –

2

これは数年後ですが、私はList<Object>の問題を解決しました。 .NET 4で

void Method(IEnumerable source) 
{ 
    var enumerator = source.GetEnumerator(); 
    if (enumerator.MoveNext()) 
    { 
     MethodInfo method = typeof(MyClass).GetMethod("Method2"); 
     MethodInfo generic; 
     Type type = enumerator.Current.GetType(); 
     bool sameType = true; 

     while (enumerator.MoveNext()) 
     { 
      if (enumerator.Current.GetType() != type) 
      { 
       sameType = false; 
       break; 
      } 
     } 

     if (sameType) 
      generic = method.MakeGenericMethod(type); 
     else 
      generic = method.MakeGenericMethod(typeof(object)); 

     generic.Invoke(this, new object[] { source }); 
    } 
} 
3

あなただけのメソッドに渡す前にdynamicsourceをキャストすることができます。これは正しい一般的な過負荷がどんな醜い反射コードなしで実行時に解決されるようになります:Jonの第二の溶液と同様に

void Method(IEnumerable source) 
{ 
    var enumerator = source.GetEnumerator(); 

    if (enumerator.MoveNext()) 
    { 
     Method2((dynamic)source); 
    } 
} 

ソースが実際にIEnumerable<T>であれば、これはのみ動作します。コンパイル時にタイプが必要です

IEnumerable<T> Convert<T>(IEnumerable source, T firstItem) 
{ 
    // Note: firstItem parameter is unused and is just for resolving type of T 
    foreach(var item in source) 
    { 
     yield return (T)item; 
    } 
} 

void Method(IEnumerable source) 
{ 
    var enumerator = source.GetEnumerator(); 

    if (enumerator.MoveNext()) 
    { 
     dynamic firstItem = enumerator.Current; 
     dynamic typedEnumerable = Convert(source, firstItem); 
     Method2(typedEnumerable); 
    } 
} 
関連する問題