简体   繁体   中英

C# convert list to Generic List

I am using vs2022 and C# language and oracle as backend. oracle procedure gets input as facility type and based on type it returns the list of data and each facility type have common columns with few additional columns per type. on the below code, MaptoList is an extension class method which maps the reader column and value to class. the below logic is not working and says cannot convert from non generic list to generic. please help me to solve the compile error.

public class Common
 {
    
         public string Name { get; set; }
         public string Address { get; set; }
         public string State{ get; set; }
    
 }
    
    
  public class Employee : Common
     {
         public string SSN{ get; set; }
     }
    
 public class Vendor : Common
     {
            
     public string TaxNumber{ get; set; }
     }
    
    
    
  public async Task<List<T>> GetFacility(string Facility_Type)
         {
             using (EMPDB dbConnect = new EMPDB())
             {
                 DbCommand dbCommand = dbConnect.Database.GetDbConnection().CreateCommand();
                 dbCommand.CommandType = CommandType.StoredProcedure;
                 dbCommand.CommandText = "GetFacilityReport";
                 dbCommand.BuildSqlParameter("Facility_Type", OracleDbType.Varchar2, Facility_Type, ParameterDirection.Input); 
                 List<T> lstFacility_Response= new List<T>();
                 if (dbCommand.Connection.State != ConnectionState.Open)
                 {
                     dbCommand.Connection.Open();
                 }
                 using (var reader = await dbCommand.ExecuteReaderAsync())
                 {
            switch (Facility_Type)
                     {    
             case "Employee":
             lstFacility_Response= reader.MapToList<Employee>();
             break;
    
             case "Vendor":
             lstFacility_Response= reader.MapToList<Vendor>();
             break;
                        
            }
                 }
                   
             }
  return lstFacility_Response
         }

public static List<T> MapToList<T>(this DbDataReader dr) where T : new()
        {
            List<T> RetVal = null;
            var Entity = typeof(T);
            var PropDict = new Dictionary<string, PropertyInfo>();
            try
            {
                if (dr != null && dr.HasRows)
                {
                    RetVal = new List<T>();
                    var Props = Entity.GetProperties(BindingFlags.Instance | BindingFlags.Public);
                    PropDict = Props.ToDictionary(p => p.Name.ToUpper(), p => p);
                    while (dr.Read())
                    {
                        T newObject = new T();
                        for (int Index = 0; Index < dr.FieldCount; Index++)
                        {
                            if (PropDict.ContainsKey(dr.GetName(Index).ToUpper()))
                            {
                                var Info = PropDict[dr.GetName(Index).ToUpper()];
                                if ((Info != null) && Info.CanWrite)
                                {
                                    var Val = dr.GetValue(Index);
                                    Info.SetValue(newObject, (Val == DBNull.Value) ? null : Val, null);
                                }
                            }
                        }
                        RetVal.Add(newObject);
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
            return RetVal;
        }

If generics are appropriate here then this:

public async Task<List<T>> GetFacility(string Facility_Type)

should be this:

public async Task<List<T>> GetFacility<T>()

and then your switch statement should be replaced with this:

lstFacility_Response = reader.MapToList<T>();

You would then call it something like so:

var list = await GetFacility<Employee>();

When declaring the method, the method itself has to be generic and then you should be able to simply use the generic type parameter as a type in the method. If you can't do that then the method almost certainly shouldn't be generic in the first place.

If you want to limit T to be only type Common or its derived types then you can add a constraint:

public async Task<List<T>> GetFacility<T>() where T : Common

Given that your MapToList method has the new constraint, this method would have to as well, in order to call MapToList<T>() :

public async Task<List<T>> GetFacility<T>() where T : Common, new()

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM