泛型 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()
——要么将限制添加到调用方法的泛型类型。
我有很多类似的 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()
——要么将限制添加到调用方法的泛型类型。