IEnumerable <t> .ConvertAll&amp; DDD </T>

时间:2010-01-08 18:12:01

标签: domain-driven-design ienumerable

我对IEumerable接口上的扩展方法有一个有趣的需求 - 与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的整个列表即可“转换”。请注意,我还更改了委托的类型 - 从Converter到Func。编译是一样的,但我认为这使我的意图更清晰 - 我不是故意这只是类型转换。

这引出了我的问题:在我的存储库层中,我有很多查询返回ID的列表 - 实体的ID。我曾经有过几个类,它们以各种方式将这些ID“转换”为实体。使用这种扩展方法,我可以将所有这些扩展到代码,如下所示:

IEnumerable<Part> GetBlueParts()
{
    IEnumerable<int> keys = GetBluePartKeys();
    return keys.ConvertAll<Part>(PartRepository.Find);
}

其中'converter'实际上是存储库的Find-by-ID方法。就我而言,'转换器'可能会做很多事情。有没有人看到这种方法有任何问题?

2 个答案:

答案 0 :(得分:10)

我用这种方法看到的主要问题是完全没必要。

您的ConvertAll方法与Enumerable.Select<TSource,TResult>(IEnumerable<TSource>, Func<TSource,TResult>)没什么区别,后者是标准的LINQ运算符。没有理由为已经在框架中的东西编写扩展方法。

你可以这样做:

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...
} 

答案 1 :(得分:1)

为什么不使用yield关键字(并且只根据需要转换每个项目)?

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");

        foreach(T item in collection)
            yield return converter(item);
    }
}