泛型 Class 加载程序:'T' 必须是具有 public 无参数构造函数的非抽象类型

Generic Class Loader: 'T' must be a non-abstract type with a public parameterless constructor

我有很多类似的 class,我正在尝试创建一个通用方法来加载每个 class 的对象列表。我没有使用任何 ORM,只是用相应的 SQL 查询加载 SqlDataReader。

我尝试过使用接口和泛型。

我只使用 2 个短 classes 简化了下面的问题:

接口:

public interface IMyEntity<T> where T : new()
{
    public List<T> ConvertToObjects(SqlDataReader dr);

    public static IMyEntity<T> CreateInstance() 
    {
        return null;
    }
}

Class 1:

public class Cat : IMyEntity<Cat>
{   
    public long CatID { get; set; } 
    public string CatName { get; set; } 
    public int OwnerID { get; set; }

    public List<Cat> ConvertToObjects(SqlDataReader dr)
    {
        List<Cat> cats = new();
        if (dr.HasRows)
        {
            while (dr.Read())
            {
                Cat cat = new()
                {
                    CatID = dr.GetInt32("CatID"),
                    CatName = dr.GetString("CatName"),
                    OwnerID = dr.GetInt32("OwnerID")
                };
                cats.Add(cat);
            }
            dr.Close();
        }
        return cats;
    }

    public IMyEntity<Cat> CreateInstance()
    {
        IMyEntity<Cat> cat = new Cat();
        return cat;
    }
}

Class 2:

public class Dog : IMyEntity<Dog>
{
    public long DogID { get; set; }
    public string DogName { get; set; }
    public int Age { get; set; }

    public List<Dog> ConvertToObjects(SqlDataReader dr)
    {
        List<Dog> dogs = new();
        if (dr.HasRows)
        {
            while (dr.Read())
            {
                Dog dog = new()
                {
                    DogID = dr.GetInt32("DogID"),
                    DogName = dr.GetString("DogName"),
                    OwnerID = dr.GetInt32("Age")
                };
                dogs.Add(dog);
            }
            dr.Close();
        }
        return dogs;
    }

    public IMyEntity<Dog> CreateInstance()
    {
        IMyEntity<Dog> dog = new Dog();
        return dog;
    }
}

我还有另一个 class 用这个方法:

public async Task<IEnumerable<T>> GetObjectAsync<T>(string procedureName)
{
    if (_connection.State != ConnectionState.Open) _connection.Open();
    SqlCommand command = new(procedureName, _connection);
    SqlDataReader dr = await cmd.ExecuteReaderAsync().ConfigureAwait(false);

    var myEntity = IMyEntity<T>.CreateInstance();
    IEnumerable<T> objs = myEntity.ConvertToObjects(dr);

    return objs;
}

带有 'CreateInstance' 的行返回以下错误:“'T' 必须是具有 public 无参数构造函数的非抽象类型才能将其用作参数 'T' 在泛型类型或方法中 'IMyEntity'"

调用方法自身的泛型类型中缺少 T : new() 约束。

public async Task<IEnumerable<T>> GetObjectAsync<T>(string procedureName)

因此编译器无法保证满足IMyEntity<T>中接口的约束要求。它与任何具体的方法调用无关,限制要求来自于接口定义本身。

public interface IMyEntity<T> where T : new()

要么从接口中删除限制——在这种情况下不能使用 new T()——要么将限制添加到调用方法的泛型类型。