I have many similar classes and I am trying to create a generic method that loads a list of objects of each class. I am not using any ORM, but just loading a SqlDataReader with the respective SQL Query.
I have tried using an interface and using generics.
I have simplified the problem below using only 2 short classes:
Interface:
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;
}
}
And I have another class with this method:
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;
}
The line with 'CreateInstance' is returning the following error: "'T' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'IMyEntity'"
The T: new()
constraint is missing in the calling method's own generic type.
public async Task<IEnumerable<T>> GetObjectAsync<T>(string procedureName)
Thus the compiler cannot guarantee the constraint requirement for the interface in IMyEntity<T>
is met. It is not related to any specific method call and the restriction requirement comes from the interface definition itself.
public interface IMyEntity<T> where T : new()
Either remove the restriction from the interface — in which case new T()
cannot be used — or add the restriction to the calling method's generic type.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.