我对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/

10-16 06:27