mercredi 16 juin 2021

Use an arbitrary object type to parse a MySql query (learning C# Reflection)

I'm trying to gain a better understanding of Generics and Reflection on C#. As an exercise, I'm executing a MySql query and trying to parse its results as predefined Objects:

//FOR TABLE A 
public class ObjectType1
    {
        public int id { get; set; }
        public String name { get; set; }
    }

 //FOR TABLE B
public class ObjectType2
    {
        public int id { get; set; }
        public timestamp expirationDate  { get; set; }    
    }

 //FOR TABLE C 
public class ObjectType3
    {
        public int id { get; set; }
        public BigDecimal price  { get; set; }
    
    }

My goal would look like this:

List<ObjectType1> listObjectsA =  selectAndCast(tableNameA, ObjectType1)
List<ObjectType2> listObjectsB =  selectAndCast(tableNameB, ObjectType2)
List<ObjectType3> listObjectsC =  selectAndCast(tableNameC, ObjectType3)

My question is, how could I specify the desired object type as a parameter? (Already checked the similar questions here at S.O., but got compilation errors).

Here's my code. Please note that some fake lines are added for clarification.

public List<Object> selectAndCast(String tableName, Object argExampleObject)
            {
    
                string connStr = "My connection parameters";
                String query = "Select * from " + tableName;
           
                MySqlConnection conn = new MySqlConnection(connStr);
    
                MySqlDataReader rdr = null;

 //  Prepares a list to store the future generated objects (fake code)

        

List <argExampleObject.GetType()> listaSalida = new List<argExampleObject.GetType() > ();

        try
        {
            conn.Open();

            MySqlCommand cmd = new MySqlCommand(query, conn);                            

            rdr = cmd.ExecuteReader();

 //  Create a dictionary that contains each column name and a consecutive number. That number will be used to locate the column by its name later
           

 Dictionary<String, int> dictionaryColumnNameVsIndex = new Dictionary<String, int>();

            for (int i = 0; i < rdr.FieldCount; i++)
            {
                String nombreColumna = rdr.GetName(i);
                dictionaryColumnNameVsIndex.Add(nombreColumna, i);
            }

            while (rdr.Read())
            {

//  For each row obtained from the query execution, create a new instance of the Example Object (fake code)

    Object <argExampleObject.GetType() > destinationObject = new Object<argExampleObject.GetType() > ();

 //  Take each column name of the row

               

 for (int i = 0; i < rdr.FieldCount; i++)
                {
                    PropertyInfo[] properties = argExampleObject.GetType().GetProperties();

                    foreach (PropertyInfo property in properties)
                    {

 //  Check if the destination object contains a property with the same name.
                       

 if (dictionaryColumnNameVsIndex.ContainsKey(property.Name))
                        {

 //  If it does, assign the value to said property.

    PropertyInfo propertyToBeChanged = destinationObject.GetProperty(property.Name));
                                    propertyToBeChanged.SetValue(rdr[dictionaryColumnNameVsIndex[property.Name]]);
                                }
                            }
                        }

 //  After all rows have been processed, return the object list
            

 listaSalida.Add(objeto);

            }

            return listaSalida;
        }
        catch (Exception ex)
        {

 //  Exception handling
        

    }
            finally
            {
                if (rdr != null)
                {
                    rdr.Close();
                    conn.Close();
                }
            }
        }




Aucun commentaire:

Enregistrer un commentaire