Class matching error: "T" must be a non-abstract type with an open constructor without parameters

When displaying a class, I get the error 'T' should be a non-abstract type with an open constructor without parameters, to use it as a parameter of 'T' in a generic type or method.

Below is my SqlReaderBase class

public abstract class SqlReaderBase<T> : ConnectionProvider { #region Abstract Methods protected abstract string commandText { get; } protected abstract CommandType commandType { get; } protected abstract Collection<IDataParameter> GetParameters(IDbCommand command); **protected abstract MapperBase<T> GetMapper();** #endregion #region Non Abstract Methods /// <summary> /// Method to Execute Select Queries for Retrieveing List of Result /// </summary> /// <returns></returns> public Collection<T> ExecuteReader() { //Collection of Type on which Template is applied Collection<T> collection = new Collection<T>(); // initializing connection using (IDbConnection connection = GetConnection()) { try { // creates command for sql operations IDbCommand command = connection.CreateCommand(); // assign connection to command command.Connection = connection; // assign query command.CommandText = commandText; //state what type of query is used, text, table or Sp command.CommandType = commandType; // retrieves parameter from IDataParameter Collection and assigns it to command object foreach (IDataParameter param in GetParameters(command)) command.Parameters.Add(param); // Establishes connection with database server connection.Open(); // Since it is designed for executing Select statements that will return a list of results // so we will call command execute reader method that return a Forward Only reader with // list of results inside. using (IDataReader reader = command.ExecuteReader()) { try { // Call to Mapper Class of the template to map the data to its // respective fields MapperBase<T> mapper = GetMapper(); collection = mapper.MapAll(reader); } catch (Exception ex) // catch exception { throw ex; // log errr } finally { reader.Close(); reader.Dispose(); } } } catch (Exception ex) { throw ex; } finally { connection.Close(); connection.Dispose(); } } return collection; } #endregion } 

What I'm trying to do, I execute some kind of command and dynamically populate my class. The class is given below:

 namespace FooZo.Core { public class Restaurant { #region Private Member Variables private int _restaurantId = 0; private string _email = string.Empty; private string _website = string.Empty; private string _name = string.Empty; private string _address = string.Empty; private string _phone = string.Empty; private bool _hasMenu = false; private string _menuImagePath = string.Empty; private int _cuisine = 0; private bool _hasBar = false; private bool _hasHomeDelivery = false; private bool _hasDineIn = false; private int _type = 0; private string _restaurantImagePath = string.Empty; private string _serviceAvailableTill = string.Empty; private string _serviceAvailableFrom = string.Empty; public string Name { get { return _name; } set { _name = value; } } public string Address { get { return _address; } set { _address = value; } } public int RestaurantId { get { return _restaurantId; } set { _restaurantId = value; } } public string Website { get { return _website; } set { _website = value; } } public string Email { get { return _email; } set { _email = value; } } public string Phone { get { return _phone; } set { _phone = value; } } public bool HasMenu { get { return _hasMenu; } set { _hasMenu = value; } } public string MenuImagePath { get { return _menuImagePath; } set { _menuImagePath = value; } } public string RestaurantImagePath { get { return _restaurantImagePath; } set { _restaurantImagePath = value; } } public int Type { get { return _type; } set { _type = value; } } public int Cuisine { get { return _cuisine; } set { _cuisine = value; } } public bool HasBar { get { return _hasBar; } set { _hasBar = value; } } public bool HasHomeDelivery { get { return _hasHomeDelivery; } set { _hasHomeDelivery = value; } } public bool HasDineIn { get { return _hasDineIn; } set { _hasDineIn = value; } } public string ServiceAvailableFrom { get { return _serviceAvailableFrom; } set { _serviceAvailableFrom = value; } } public string ServiceAvailableTill { get { return _serviceAvailableTill; } set { _serviceAvailableTill = value; } } #endregion public Restaurant() { } } } 

To dynamically populate class properties, I have another class called the MapperBase class with the following methods:

  public abstract class MapperBase<T> where T : new() { protected T Map(IDataRecord record) { T instance = new T(); string fieldName; PropertyInfo[] properties = typeof(T).GetProperties(); for (int i = 0; i < record.FieldCount; i++) { fieldName = record.GetName(i); foreach (PropertyInfo property in properties) { if (property.Name == fieldName) { property.SetValue(instance, record[i], null); } } } return instance; } public Collection<T> MapAll(IDataReader reader) { Collection<T> collection = new Collection<T>(); while (reader.Read()) { collection.Add(Map(reader)); } return collection; } } 

There is another class that inherits SqlreaderBaseClass, called DefaultSearch. Code below

  public class DefaultSearch: SqlReaderBase<Restaurant> { protected override string commandText { get { return "Select Name from vw_Restaurants"; } } protected override CommandType commandType { get { return CommandType.Text; } } protected override Collection<IDataParameter> GetParameters(IDbCommand command) { Collection<IDataParameter> parameters = new Collection<IDataParameter>(); parameters.Clear(); return parameters; } protected override MapperBase<Restaurant> GetMapper() { MapperBase<Restaurant> mapper = new RMapper(); return mapper; } } 

But whenever I tried to build, I get the error message "T" must be a non-abstract type with an open constructor without parameters in order to use it as a parameter "T" in a generic type or method. Even here T has a restaurant with Constructless Public.

+45
c # mapping abstract-class
Jun 16 '10 at 20:17
source share
3 answers

The problem is that you are trying to use T from SqlReaderBase as a type argument for MapperBase - but you have no restrictions on T

Try changing the SqlReaderBase to the following:

 public abstract class SqlReaderBase<T> : ConnectionProvider where T : new() 

Here is a shorter example demonstrating the same problem:

 class Foo<T> { Bar<T> bar; } class Bar<T> where T : new() { } 

The fix is ​​to change the declaration of Foo<T> to:

 class Foo<T> where T : new() 

Then the compiler will know that T from Foo is a valid type argument for Bar .

+79
Jun 16 '10 at 20:24
source share

Constraints should apply to each type in the chain; so you need to:

 public abstract class SqlReaderBase<T> : ConnectionProvider where T : new() 

Without this, you cannot satisfy the restriction for T in:

 protected abstract MapperBase<T> GetMapper(); 

or

 MapperBase<T> mapper = GetMapper(); 

since MapperBase<> can only be used when T has : new()

+9
Jun 16 '10 at 20:24
source share

I had the same problem. I had to read the message before ruining it. I needed to add a constructor without parameters ... :-)

 public MyClass() { //stuff } 
+1
Jun 21 '16 at 12:42 on
source share



All Articles