[英]How do I create a dynamically typed C# iterator block?
I am doing an AOP kind of layer and I would like to return an iterator block for a generic collection (ie something like "IEnumerable"). 我正在做一种AOP层,我想为通用集合返回一个迭代器块(即类似“ IEnumerable”的东西)。 However, the type T is dynamically discovered. 但是,类型T是动态发现的。 I can find that type and have it locally as a "Type" variable but how do I go beyond that and return an iterator block for that dynamically-discovered type? 我可以找到该类型,并在本地将其作为“类型”变量,但是如何超越该类型并为该动态发现的类型返回迭代器块?
What I want is something like this (as close as I can express it in conventional 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;
}
I would like to then return the EntryIteratorBlock so that I can dynamically walk through the collection. 然后,我想返回EntryIteratorBlock,以便我可以动态遍历集合。 (The elements in the collection are expensive to load and so I want to load them lazily.) (集合中的元素加载起来很昂贵,因此我想延迟加载它们。)
The compiler has to work out the return type of calls to EntryIteratorBlock
, which it cannot do with a runtime type. 编译器必须计算出对EntryIteratorBlock
的返回类型,而对于运行时类型则不能。 IEnumerator<runtimeDiscoveredType>
is a contradiction in terms. IEnumerator<runtimeDiscoveredType>
在术语上是矛盾的。
The most information you have at compile-time is that the sequence will contain objects: 您在编译时获得的最多信息是该序列将包含对象:
public IEnumerator<object> EntryIteratorBlock(Type desiredElementType)
{
// ...
}
Or, if the items in the sequence share a common type: 或者,如果序列中的项目具有共同的类型:
public IEnumerator<BaseElementType> EntryIteratorBlock(Type desiredElementType)
{
// ...
}
If you post some information about the problem you are trying to solve with the iterator, we might be able to offer help at a more fundamental level. 如果您发布有关您要使用迭代器解决的问题的信息,我们也许可以在更基本的层面上提供帮助。
Although it's not clear that this is the right way to do this, here's a way that works: 尽管目前尚不清楚这是否是正确的方法,但这是一种可行的方法:
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);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.