如何为 ICollection<T> where T : IMyInterface 定义扩展方法而不在方法定义中指定 T

How to Define Extension Method for ICollection<T> where T : IMyInterface without Specifying T in the Method Definition

背景:我想在将 DTO 映射到实体时加入业务规则。我认为将映射封装到扩展方法中将是一个很好的途径。

IEntityDto是所有可以直接映射到实体的DTO实现的接口。

单个实例工作正常:

public static TEntity MapTo<TEntity>(this IEntityDto dto)
{
    ... Run Business Rules that don't require db access ...
    return AutoMapper.Mapper.Map<TEntity>(dto);
}

我也想以同样的方式扩展 ICollection:

public static ICollection<TEntity> MapToCollection<TEntity>(this ICollection<IEntityDto> dtos)
{
    ... Run Business Rules that don't require db access ...
    return AutoMapper.Mapper.Map<ICollection<TEntity>>(dtos);
}

不幸的是,当应用于 IEntityDto 的 ICollection 时,MapToCollection 不会显示在上下文菜单中或编译。

我缺少什么才能让它工作?我是否只需要在 T 是 IEntityDto 的地方扩展 ICollection?我希望在调用扩展方法时不必包含 DTO 类型。

public static ICollection<TEntity>MapToCollection<TDto,TEntity>(this ICollection<TDto> dtos) where TDto: IEntityDto
{
    ... Do Work and Return ...
}

以上有效,但我希望从集合中推断出 T。

谢谢!

我假设发生这种情况是因为您要调用此扩展方法的变量实际上不是 ICollection<IEntityDto> 类型,而是 ICollection<MyEntityDto> 类型。

试试这个:

public static class ExtensionMethods
{
    public static ICollection<TEntity> MapToCollection<TEntity, TEntityDto>(
        this ICollection<TEntityDto> dtos) where TEntityDto : IEntityDto
    {
        return AutoMapper.Mapper.Map<ICollection<TEntity>>(dtos);
    }        
}

此方法接受通用 ICollection<TEntityDto> 而不是 ICollection<IEntityDto>,这使其适用于 ICollection<MyEntityDto>.

等情况

以下是您将如何使用它:

Collection<MyEntityDto> collection = ...

var result = collection.MapToCollection<MyEntity, MyEntityDto>();

有效地需要一个签名为

的方法
public static ICollection<TEntity> MapToCollection<TEntity, TEntityDto>(
    this ICollection<TEntityDto> dtos)
    where TEntityDto : IEntityDto

...但这会迫使您指定 both 类型参数,我知道您不想这样做。

你可以做的是分两步进行,例如

public static class DtoExtensions
{
    public static CollectionMapper<TEntityDto> Map(this ICollection<TEntityDto> dtos)
        where TEntityDto : IEntityDto
    {
        return new CollectionMapper<TEntityDto>(dtos);
    }
}

public class CollectionMapper<TEntityDto> where TEntityDto : IEntityDto
{
    private readonly ICollection<TEntityDto> dtos;

    public CollectionMapper(ICollection<TEntityDto> dtos)
    {
        this.dtos = dtos;
    }

    public ICollection<TEntity> To<TEntity>()
    {
        // Business rules...
        return AutoMapper.Mapper.Map<ICollection<TEntity>>(dtos);
    }
}

您现在可以使用:

var result = collection.Map().To<FooEntity>();

Map 调用推断 TEntityDto,并且您在 To 调用中指定 TEntity