簡體   English   中英

類映射錯誤:“ T”必須是具有公共無參數構造函數的非抽象類型

[英]Class Mapping Error: 'T' must be a non-abstract type with a public parameterless constructor

在映射類我遇到錯誤“ T”的同時,它必須是具有公共無參數構造函數的非抽象類型,才能在通用類型或方法中將其用作參數“ T”。

下面是我的SqlReaderBase類

 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's 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
    }

我想做的是,我執行一些命令並動態填充我的班級。 該類如下:

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() { }

    }
}

為了動態地填充我的類屬性,我使用以下方法創建了另一個名為MapperBase類的類:

 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;
        }

    }

還有另一個類繼承了SqlreaderBaseClass,稱為DefaultSearch。 代碼如下

 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;
    }
}

但是,每當我嘗試構建時,都會出現錯誤“ T”必須是具有公共無參數構造函數的非抽象類型,以便將其用作通用類型或方法中的參數“ T”。 甚至T這里的餐廳都有一個無參數公共構造函數。

問題是,你要使用TSqlReaderBase作為類型參數MapperBase -但你沒有這方面任何約束T

嘗試將SqlReaderBase聲明更改為此:

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

這是一個較短的示例,它演示了相同的問題:

class Foo<T>
{
    Bar<T> bar;
}

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

解決方法是將Foo<T>的聲明更改為:

class Foo<T> where T : new()

然后,編譯器將知道Foo中的TBar的有效類型參數。

約束必須適用於鏈中的每種類型。 因此,您需要:

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

沒有這個,就不能滿足T中的約束:

protected abstract MapperBase<T> GetMapper();

要么

MapperBase<T> mapper = GetMapper();

因為MapperBase<> T具有時才可用: new()

我遇到過同樣的問題。 在谷歌搜索之前,我應該已經閱讀了該消息。 我需要添加一個無參數的構造函數... :-)

public MyClass() {
  //stuff
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM