如何将一个通用类型的数据列表转换为另一个通用类型的数据列表

6
我正在尝试编写一个“通用基础服务类”,在接收到第一个泛型数据列表作为“Db Model Entity”类型后,需要将其转换为新的“Generic View Model”类型的数据。
我尝试使用“list.ConvertAll()”,但是总是遇到“ConvertAll()”方法的构建错误。
我还尝试了“list.Cast().ToList()”,这解决了构建错误,但却得到了运行时错误。
以下是所有类和接口的代码片段。感谢任何帮助或建议。
实体类:
public abstract class Entity
{
    [Key]
    [Index("IX_Id", 1, IsUnique = true)]
    public string Id { get; set; }

    [DataType(DataType.DateTime)]
    public DateTime Created { get; set; }

    public string CreatedBy { get; set; }

    [DataType(DataType.DateTime)]
    public DateTime Modified { get; set; }

    public string ModifiedBy { get; set; }

    [DefaultValue(true)]
    public bool Active { get; set; }
}

BaseViewModel类

public abstract class BaseViewModel<T> where T: Entity
{        

    protected BaseViewModel() { }

    protected BaseViewModel(T model)
    {
        Id = model.Id;
        Created = model.Created;
        CreatedBy = model.CreatedBy;
        Modified = model.Modified;
        ModifiedBy = model.ModifiedBy;
        Active = model.Active;
    }

    public string Id { get; set; }
    public DateTime Created { get; set; }
    public string CreatedBy { get; set; }
    public DateTime Modified { get; set; }
    public string ModifiedBy { get; set; }
    public bool Active { get; set; }
}

IBaseService interface

public interface IBaseService<T, TVm> where T : Entity where TVm : BaseViewModel<T>
{
    List<TVm> GetAll();
}

BaseService Class

public abstract class BaseService<TEntity, TVm> : IBaseService<TEntity, TVm> where TEntity: Entity where TVm : BaseViewModel<TEntity>
{
    protected  IBaseRepository<TEntity> Repository;

    protected BaseService(IBaseRepository<TEntity> repository)
    {
        Repository = repository;
    }

    public virtual  List<TVm> GetAll()
    {
        List<TVm> entities;
        try
        {
            List<TEntity> list = Repository.GetAll().ToList();
            entities =  list.Cast<TVm>().ToList(); //runtime error
            entities = list.ConvertAll(x => new TVm(x)); //build error
            entities = list.ConvertAll(new Converter<TEntity, TVm>(TEntity)); //build error
        }
        catch (Exception exception)
        {                
            throw new Exception(exception.Message);
        }

        return entities;
    }

}

它给你什么构建错误?还有什么运行时错误?请修改问题。 - Foyzul Karim
2个回答

2
要创建一个泛型类型的实例,您需要在其上使用new()约束。但是,这并不允许您向其传递任何参数。您可以尝试以下两种方法之一:
  1. 使用Activator创建一个实例,像这样:entities = list.ConvertAll(x => (TVm)Activator.CreateInstance(typeof(TVm), x));
  2. BaseService类签名中添加new()约束到TVm,并在您作为TVm传递给它的类上添加一个方法,该方法基本上执行当前构造函数所做的操作,但在方法中执行,并在创建新对象后调用该方法。

你也可以使用映射工具,例如AutoMapper(https://github.com/AutoMapper/AutoMapper)。 - Alexey Nis
1
1非常有用且运行良好。在提问之前,我已经尝试过2,但它破坏了我的当前实现。这就是为什么我拒绝添加new()约束的原因。非常感谢您的友善回答。 - Md. Sabbir Ahamed

0

我认为你尝试的最佳选择是 entities = list.ConvertAll(x => new TVm(x));。它在编译时失败的原因是,在 C# 中,派生类不一定需要有与基类相同的构造函数。相反,你应该在 BaseService 内初始化 TVm。此外,你的 try catch 块除了丢失一些数据并影响 StackTrace 外,什么也做不了,所以最好将其删除。 下面的代码应该适用于你。

public abstract class BaseService<TEntity, TVm> 
    : IBaseService<TEntity, TVm> 
        where TEntity: Entity 
        where TVm : BaseViewModel<TEntity>, new()
{
    protected  IBaseRepository<TEntity> Repository;

    protected BaseService(IBaseRepository<TEntity> repository)
    {
        Repository = repository;
    }

    private TVm ConvertToViewModel(TEntity model)
    {
        return new TVm
        {
            Id = model.Id,
            Created = model.Created,
            CreatedBy = model.CreatedBy,
            Modified = model.Modified,
            ModifiedBy = model.ModifiedBy,
            Active = model.Active,
        };
    }

    public virtual  List<TVm> GetAll()
    {
        List<TEntity> list = Repository.GetAll().ToList();
        List<TVm> entities = list.ConvertAll(x => ConvertToViewModel(x));
        return entities;
    }
}

感谢您的建议。因此,我没有使用new()约束,无法创建TVm的实例。 - Md. Sabbir Ahamed
@Md.SabbirAhamed,由于我不熟悉整个情况,所以添加new()约束可能对您来说是不可接受的。无论如何,我很高兴您的问题已得到解决。 - Adil Mammadov
1
是的,我很高兴问题已经解决:)。再次感谢你。显然,你分享的知识可能在将来的我的项目中或其他任何项目中都非常有效。 - Md. Sabbir Ahamed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接