2010-11-23 20 views
1

AOPの種類のレイヤを実行しています。ジェネリックコレクション(IEnumerableなど)のイテレータブロックを返したいとします。しかし、タイプTは動的に発見される。私はその型を見つけることができ、それを "型"変数としてローカルに持っていますが、それを越えて、その動的に発見された型のイテレータブロックを返すにはどうしたらいいですか?私が欲しいもの動的に型指定されたC#イテレータブロックを作成するにはどうすればよいですか?

は、この(私は、従来のC#でそれを表現することができます近くなどのような)のようなものです:

public IEnumerator<runtimeDiscoveredType> EntryIteratorBlock(Type desiredElementType) 
{ 
    // One can assume that desireElementType is the same as (or convertible to) runtimeDiscoveredType 
    TypeConverter tc = new TypeConverter() 
    var actualItem = ....; // some code goes here to pick up the actual item from 
    ...     // some collection. 

    if (ChooseThisItem(actualItem)) 
     yield return tc.ConvertTo(actualItem, desiredElementType); 
    else 
     yield break; 
} 

私は動的コレクションを歩くことができるように、そして、EntryIteratorBlockを返すようにしたいと思います。 (コレクションの要素が読み込みに時間がかかるため、遅延読み込みを行いたい)

+0

私はピーターに同意します。より具体的な例は、あなたがやろうとしていることを書いているかどうかを簡単に伝えることができます。 – Gabe

答えて

0

それは、これがこれを行うための正しい方法であることは明らかではないですが、ここで働く方法です:

class Program 
{ 
    // this method is not called directly 
    // but it is public so it is found by reflection 
    public static IEnumerable<U> EntryIteratorBlock<T, U>(
     IEnumerable<T> source, Func<object, bool> selector) 
    { 
     TypeConverter tc = new TypeConverter(); 
     foreach (T item in source) 
      if (selector(item)) 
       yield return (U)tc.ConvertTo(item, typeof(U)); 
    } 

    static IEnumerable CreateIterator(
     // these are the type parameters of the iterator block to create 
     Type sourceType, Type destType, 
     // these are the parameters to the iterator block being created 
     IEnumerable source, Func<object, bool> selector) 
    { 
     return (IEnumerable) typeof(Program) 
      .GetMethod("EntryIteratorBlock") 
      .MakeGenericMethod(sourceType, destType) 
      .Invoke(null, new object[] { source, selector }); 
    } 

    static void Main(string[] args) 
    { 
     // sample code prints "e o w o" 
     foreach (var i in CreateIterator(typeof(char), typeof(string), 
          "Hello, world", c => ((char)c & 1) == 1)) 
      Console.WriteLine(i); 
    } 
} 
+0

はい、これは私が探していたものです。ありがとうございました。 – Tevya

3

コンパイラは、戻り値の型をEntryIteratorBlockに変換する必要があります。これは実行時の型では実行できません。 IEnumerator<runtimeDiscoveredType>は矛盾しています。

public IEnumerator<object> EntryIteratorBlock(Type desiredElementType) 
{ 
    // ... 
} 

あるいは、もしシーケンス共有の項目一般的なタイプ:

public IEnumerator<BaseElementType> EntryIteratorBlock(Type desiredElementType) 
{ 
    // ... 
} 

あなたの場合

あなたはコンパイル時に持っているほとんどの情報は、シーケンスオブジェクトを含むということですイテレータで解決しようとしている問題に関する情報を投稿すると、より基本的なレベルでヘルプを提供できる可能性があります。

関連する問題