如何在扩展方法中获取'this'参数的泛型类型参数?



我正在尝试将以下方法转换为IEnumerable上的扩展方法:

private static IEnumerable<TTarget> MapList<TSource, TTarget>(IEnumerable<TSource> source)
{
    return source.Select(
            element =>
                _mapper.Map<TSource, TTarget>(element)
        ).ToList();
}

现在是这样的:

var sourceList = new List<SourceType>();
return MapList<SourceType, TargetType>(sourceList);

但是我想这样命名它:

var sourceList = new List<SourceType>();
return sourceList.MapTo<TargetType>();

我已经试过了:

public static IEnumerable<TTarget> MapTo<TTarget>(this IEnumerable<TSource> source)
{
    return source.Select(
            element =>
                Mapper.Map<TSource, TTarget>(element)
        ).ToList();
}    

但是我没有找到类型或命名空间TSource,因为它没有包含在方法的类型参数列表中。我可以这样设置:

public static IEnumerable<TTarget> MapTo<TSource, TTarget>(this IEnumerable<TSource> source)
{
    return source.Select(
            element =>
                Mapper.Map<TSource, TTarget>(element)
        ).ToList();
}

但是这个我必须这样命名:

var sourceList = new List<SourceType>();
sourceList.MapTo<SourceType, TargetType>();

我觉得不像sourceList.MapTo<TargetType>()那么清楚。

有办法做我想做的吗?

调用中没有足够的信息来完全确定要传递给MapTo的泛型类型参数,并且c#不支持仅推断某些类型。要么指定所有类型,要么一个都不指定。

然而,你可以通过重新设计你的界面来解决这个问题。这里只有一个解决方案:

public sealed class Mappable<TSource>
{
    private readonly IEnumerable<TSource> source;
    public Mappable(IEnumerable<TSource> source)
    {
        this.source = source;
    }
    public IEnumerable<TTarget> To<TTarget>()
    {
        return source.Select(
                element =>
                    Mapper.Map<TSource, TTarget>(element)
            ).ToList();
    }
}
public static class Extensions
{
    public static Mappable<TSource> Map<TSource>(this IEnumerable<TSource> source)
    {
        return new Mappable<TSource>(source);
    }
}

现在你可以这样称呼它:

var sourceList = new List<SourceType>();
var target = sourceList.Map().To<TargetType>();

或者,如果你放弃使用扩展方法,你可以这样做:

public static class MapTo<TTarget>
{
    public static IEnumerable<TTarget> From<TSource>(IEnumerable<TSource> source)
    {
        return source.Select(
                element =>
                    Mapper.Map<TSource, TTarget>(element)
            ).ToList();
    }
}

然后这样命名:

var sourceList = new List<SourceType>();
var target = MapTo<TargetType>.From(sourceList);

这两个都不是特别优雅。如果您喜欢这种语法而不是在每次调用时完全指定泛型参数,则由您决定。

最新更新