【问题标题】:How can I get the generic type parameter of the 'this' parameter in an extension method?如何在扩展方法中获取“this”参数的泛型类型参数?
【发布时间】:2014-06-11 21:45:19
【问题描述】:

我正在尝试将以下方法转换为 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&lt;TargetType&gt;()那么清楚。

有什么方法可以做我想做的事吗?

【问题讨论】:

标签: c# generics extension-methods


【解决方案1】:

调用中没有足够的信息来完全确定要传递给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);

这些都不是特别优雅。如果您更喜欢这种语法而不是在每次调用中完全指定通用参数,这取决于您。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-24
    相关资源
    最近更新 更多