我对IEumerable接口(interface)上的扩展方法有一个有趣的需求-与List.ConvertAll相同。在here之前已经讨论了这一点,我找到了一个解决方案here。我对该解决方案不满意的是,他构建了一个List来保存转换后的对象,然后将其返回。我怀疑LINQ在他写文章时不可用,所以我的实现是这样的:
public static class IEnumerableExtension
{
public static IEnumerable<TOutput> ConvertAll<T, TOutput>(this IEnumerable<T> collection, Func<T, TOutput> converter)
{
if (null == converter)
throw new ArgumentNullException("converter");
return from item in collection
select converter(item);
}
}
我对此更满意的是,我可以“即时”转换,而不必加载任何TOutput的整个列表。请注意,我还更改了委托(delegate)的类型-从Converter更改为Func。编译是相同的,但我认为它使我的意图更清楚了-我并不是说要进行类型转换。
这使我想到了一个问题:在我的存储库层中,我有很多查询都返回ID的列表-实体的ID。我曾经有几个类以各种方式将这些ID“转换”为实体。通过这种扩展方法,我可以将所有内容简化为如下代码:
IEnumerable<Part> GetBlueParts()
{
IEnumerable<int> keys = GetBluePartKeys();
return keys.ConvertAll<Part>(PartRepository.Find);
}
“转换器”实际上是存储库的“按ID查找”方法。就我而言,“转换器”可能会做很多工作。有人看到这种方法有什么问题吗?
最佳答案
我看到的这种方法的主要问题是完全没有必要。
您的ConvertAll
方法与标准LINQ运算符 Enumerable.Select<TSource,TResult>(IEnumerable<TSource>, Func<TSource,TResult>)
没什么不同。没有理由为框架中已有的东西编写扩展方法。
您可以这样做:
IEnumerable<Part> GetBlueParts()
{
IEnumerable<int> keys = GetBluePartKeys();
return keys.Select<int,Part>(PartRepository.Find);
}
注意:您的方法也将需要
<int,Part>
进行编译,除非PartRepository.Find
仅适用于int,并且仅返回Part实例。如果要避免这种情况,可以执行以下操作:IEnumerable<Part> GetBlueParts()
{
IEnumerable<int> keys = GetBluePartKeys();
return keys.Select(i => PartRepository.Find<Part>(i)); // I'm assuming that fits your "Find" syntax...
}
关于domain-driven-design - IEnumerable <T> .ConvertAll和DDD,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2029660/