0

how to create class and List dynamically in C#, for ex:if we pass data-set to method that should return List formatted Data

but on conventional model Each time i need to create class and method, so anybody having ideas pls share it.

Here is my conventional method Code:-

[WebMethod]
    public static List<ICF> ge_Grid_data(string paramstr, string procname)
    {
        #region
        List<ICF> lst = new List<ICF>();
        try
        {
            string[] parameters = paramstr.Split('~');
            string err = string.Empty;
            int len = parameters.Length;
            SqlParameter[] sqlParam = new SqlParameter[len];
            for (int i = 0; i < len; i++)
            {
                string[] paramWithValue = parameters[i].Split('$');
                string param = paramWithValue[0].ToString();
                string value = paramWithValue[1].ToString();
                sqlParam[i] = new SqlParameter { ParameterName = param, Value = value };
            }

            DataSet ds = new clsiCMSBLBase().GetListData(ref err, sqlParam, procname);
            DataTable dt = ds.Tables[0];
            foreach (DataRow dr in dt.Rows)
            {
                ICF obj = new ICF();
                obj.Flag = Convert.ToInt32(dr["Flag"]);
                obj.ClaimID = dr["ClaimID"].ToString();
                obj.RyotNumber = dr["RyotNumber"].ToString();
                obj.SeasonCode = dr["SeasonCode"].ToString();
                obj.PlotNumber = dr["PlotNumber"].ToString();
                obj.RyotNumber = dr["RyotNumber"].ToString();
                obj.RyotName = dr["RyotName"].ToString();
                obj.ClaimDate = dr["ClaimDate"].ToString();
                obj.ClaimFormNo = dr["ClaimFormNo"].ToString();
                obj.ClaimArea = dr["ClaimArea"].ToString();
                obj.ClaimAmount = dr["ClaimAmount"].ToString();
                obj.ClaimReason = dr["ClaimReason"].ToString();
                obj.SurveyorID = dr["SurveyorID"].ToString();
                obj.SurveyorDate = dr["SurveyorDate"].ToString();
                obj.InsuranceAmount = dr["InsuranceAmount"].ToString();

                lst.Add(obj);
            }
        }
        catch (Exception ex)
        {
        }

        return lst;
        #endregion
    }

Here is ICF Class:-

public class ICF
    {
        #region
        public int Flag { get; set; }
        public string ClaimID { get; set; }
        public string SeasonCode { get; set; }
        public string PlotNumber { get; set; }
        public string RyotNumber { get; set; }
        public string RyotName { get; set; }
        public string ClaimDate { get; set; }
        public string ClaimFormNo { get; set; }
        public string ClaimArea { get; set; }
        public string ClaimAmount { get; set; }
        public string ClaimReason { get; set; }
        public string SurveyorID { get; set; }
        public string SurveyorDate { get; set; }
        public string InsuranceAmount { get; set; }
        #endregion
    }

My Expectation:

    public static class Extensions
{
    /// <summary>
    /// Converts datatable to list<T> dynamically
    /// </summary>
    /// <typeparam name="T">Class name</typeparam>
    /// <param name="dataTable">data table to convert</param>
    /// <returns>List<T></returns>
    public static List<T> ToList<T>(this DataTable dataTable) where T : new()
    {
        var dataList = new List<T>();

        //Define what attributes to be read from the class
        const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;

        //Read Attribute Names and Types
        var objFieldNames = typeof(T).GetProperties(flags).Cast<PropertyInfo>().
            Select(item => new 
            { 
                Name = item.Name, 
                Type = Nullable.GetUnderlyingType(item.PropertyType) ?? item.PropertyType 
            }).ToList();

        //Read Datatable column names and types
        var dtlFieldNames = dataTable.Columns.Cast<DataColumn>().
            Select(item => new { 
                Name = item.ColumnName, 
                Type=item.DataType 
            }).ToList();

        foreach (DataRow dataRow in dataTable.AsEnumerable().ToList())
        {
            var classObj = new T();

            foreach (var dtField in dtlFieldNames)
            {
                PropertyInfo propertyInfos = classObj.GetType().GetProperty(dtField.Name);

                var field = objFieldNames.Find(x => x.Name == dtField.Name);

                if (field != null)
                {

                    if (propertyInfos.PropertyType == typeof(DateTime))
                    {
                        propertyInfos.SetValue
                        (classObj, convertToDateTime(dataRow[dtField.Name]), null);
                    }
                    else if (propertyInfos.PropertyType == typeof(int))
                    {
                        propertyInfos.SetValue
                        (classObj, ConvertToInt(dataRow[dtField.Name]), null);
                    }
                    else if (propertyInfos.PropertyType == typeof(long))
                    {
                        propertyInfos.SetValue
                        (classObj, ConvertToLong(dataRow[dtField.Name]), null);
                    }
                    else if (propertyInfos.PropertyType == typeof(decimal))
                    {
                        propertyInfos.SetValue
                        (classObj, ConvertToDecimal(dataRow[dtField.Name]), null);
                    }
                    else if (propertyInfos.PropertyType == typeof(String))
                    {
                        if (dataRow[dtField.Name].GetType() == typeof(DateTime))
                        {
                            propertyInfos.SetValue
                            (classObj, ConvertToDateString(dataRow[dtField.Name]), null);
                        }
                        else
                        {
                            propertyInfos.SetValue
                            (classObj, ConvertToString(dataRow[dtField.Name]), null);
                        }
                    }
                }                
            }
            dataList.Add(classObj);
        }
        return dataList;
    }

    private static string ConvertToDateString(object date) 
    {
        if (date == null)
            return string.Empty;

        return SpecialDateTime.ConvertDate(Convert.ToDateTime(date));
    }

    private static string ConvertToString(object value)
    {
        return Convert.ToString(HelperFunctions.ReturnEmptyIfNull(value));
    }

    private static int ConvertToInt(object value) 
    {
        return Convert.ToInt32(HelperFunctions.ReturnZeroIfNull(value));
    }

    private static long ConvertToLong(object value)
    {
        return Convert.ToInt64(HelperFunctions.ReturnZeroIfNull(value));
    }

    private static decimal ConvertToDecimal(object value)
    {
        return Convert.ToDecimal(HelperFunctions.ReturnZeroIfNull(value));
    }

    private static DateTime convertToDateTime(object date)
    {
        return Convert.ToDateTime(HelperFunctions.ReturnDateTimeMinIfNull(date));
    }
}

Finally, i need to call it like this:

List<MyClass> list =  dt.ToList<MyClass>

but this code not working

ethiraj
  • 67
  • 11
  • I'm not quite sure what you're asking, but are you talking about automatic mapping? or literally as you get arbitrary data in, you want to automatically generate the corresponding cs classes for it and make that a part of your solution? Could I ask why you want to achieve this if this is the case? – Callum Linington Feb 20 '17 at 10:44
  • 2
    Explain your use case first. Seems strange that you want to map a generic model to a strongly typed model that is generated on the fly. – L-Four Feb 20 '17 at 10:46
  • yes automatic mapping, because on each time i need to create so many List method for return List Data's to HTML page, so if i having common List Method means can reduce again again development – ethiraj Feb 20 '17 at 10:48
  • You can do `dt.AsEnumerable().Select(dr => new ICF{Flag = Convert.ToInt32(dr["Flag"]), //other property mappings}).ToList();` instead of `foreach`. or use `AutoMapper` or related object mappers – Developer Feb 20 '17 at 10:55
  • yes i could take your point of ideas, but my expectation should be fully automatically return data's as List, like Reusable model. there should not add any column name or any Class object name or Class name – ethiraj Feb 20 '17 at 11:07
  • Why do you need it as classes? It *seems* like you need a list of a `KeyValuePair` but it's really hard to say without knowing how you are expecting to use it. "return List Data's to HTML page" doesn't say much. – default Feb 20 '17 at 11:16
  • DataTable is not enumerable only the rows. dt.AsEnumerable() gets the rows of the table. So you would need something like this : List list = dt.AsEnumerable().ToList – jdweng Feb 20 '17 at 11:23
  • Mr. Default, pls review My Expectation code, there is fully everything auto mapping, so in future development easy to develop that's what i'm asking – ethiraj Feb 20 '17 at 11:30

3 Answers3

0

Although it's not quite clear what you want to achieve, you could use the dynamic keyword and System.Dynamic.ExpandoObject with .Net >= 4 to do what you've described.

JeffRSon
  • 10,404
  • 4
  • 26
  • 51
  • just i'm pushing the data one by one manually okay, but i need to do everything automated way – ethiraj Feb 20 '17 at 10:50
  • just view above mentioned code data-set return from DB and pushing to FOR-EACH loop then i call ICF Class here is only i'm asking dynamic class(ICF) then i need to push this kind of objects on each time different access obj.ClaimAmount = dr["ClaimAmount"].ToString(); and return List – ethiraj Feb 20 '17 at 10:54
  • Hmmm - you could serialize your `DataTable` to JSON (http://stackoverflow.com/questions/2979922/how-to-convert-datatable-to-json-string-using-json-net) and deserialize to dynamic (http://stackoverflow.com/questions/4535840/deserialize-json-object-into-dynamic-object-using-json-net). If you absolutely need to, that is... – JeffRSon Feb 20 '17 at 10:58
0

Create a method in the class ICF

    public class ICF
    {
        public static List<ICF> icfList = new List<ICF>();

        #region
        public int Flag { get; set; }
        public string ClaimID { get; set; }
        public string SeasonCode { get; set; }
        public string PlotNumber { get; set; }
        public string RyotNumber { get; set; }
        public string RyotName { get; set; }
        public string ClaimDate { get; set; }
        public string ClaimFormNo { get; set; }
        public string ClaimArea { get; set; }
        public string ClaimAmount { get; set; }
        public string ClaimReason { get; set; }
        public string SurveyorID { get; set; }
        public string SurveyorDate { get; set; }
        public string InsuranceAmount { get; set; }
        #endregion


        public static void AddRow(DataRow dr)
        {
                ICF obj = new ICF();
                obj.Flag = Convert.ToInt32(dr["Flag"]);
                obj.ClaimID = dr["ClaimID"].ToString();
                obj.RyotNumber = dr["RyotNumber"].ToString();
                obj.SeasonCode = dr["SeasonCode"].ToString();
                obj.PlotNumber = dr["PlotNumber"].ToString();
                obj.RyotNumber = dr["RyotNumber"].ToString();
                obj.RyotName = dr["RyotName"].ToString();
                obj.ClaimDate = dr["ClaimDate"].ToString();
                obj.ClaimFormNo = dr["ClaimFormNo"].ToString();
                obj.ClaimArea = dr["ClaimArea"].ToString();
                obj.ClaimAmount = dr["ClaimAmount"].ToString();
                obj.ClaimReason = dr["ClaimReason"].ToString();
                obj.SurveyorID = dr["SurveyorID"].ToString();
                obj.SurveyorDate = dr["SurveyorDate"].ToString();
                obj.InsuranceAmount = dr["InsuranceAmount"].ToString();

                icfList.Add(obj);
        }
    }
jdweng
  • 33,250
  • 2
  • 15
  • 20
  • that should be fully automatic Reuse model, so there should not add manual line of code or class or class object – ethiraj Feb 20 '17 at 11:09
0

**

i got answer Here is serialised data and easy to access in HTML page using Jquery Ajax method, this is Re-usable code like common method just pass SP name, parameter, table order(0th table or 1st table whatever your wish), this model can use for fill data to controls or jqx widget grid bind..,etc

**

[WebMethod]
public static String GetRowData_Tables(string procedureName, string paramstr, int table)
{
    string[] parameters = paramstr.Split('~');
    string err = string.Empty;
    int len = parameters.Length;
    SqlParameter[] sqlParam = new SqlParameter[len];
    for (int i = 0; i < len; i++)
    {
        string[] paramWithValue = parameters[i].Split('$');
        string param = paramWithValue[0].ToString();
        string value = paramWithValue[1].ToString();
        sqlParam[i] = new SqlParameter { ParameterName = param, Value = value };
    }

    try
    {
        DataSet ds = new clsiCMSBLBase().GetListData(ref err, sqlParam, procedureName);
        String JSONString = String.Empty;

        //JSONString = Newtonsoft.Json.JsonConvert.SerializeObject(ds, Newtonsoft.Json.Formatting.Indented);

        if (ds.Tables[table].Rows.Count > 0)
        {
            DataTable dt = ds.Tables[table];
            JSONString = Newtonsoft.Json.JsonConvert.SerializeObject(dt, Newtonsoft.Json.Formatting.Indented);
        }

        return JSONString;
    }
    catch (Exception)
    {
        return "Error";
    }
}
ethiraj
  • 67
  • 11