zoukankan      html  css  js  c++  java
  • 学习反射之将List<T>自定义导出

    学习反射之将List<T>自定义导出

    1.前言:最近有个Task需要操作很多大表(每个表的列名都上百),需要将这些表数据从不同数据源中找到,然后将表导入到数据库,可能还得需要将表部分数据导出成各种文件(csv,txt,excel等)。

     

    2.思考:一般像这种需求.先定义一个TemplateInfo,然后去DB为这个TemplateInfo创建一个表。最后封装TemplateManager定义一些操作DB的方法。

    现在问题产生了:需要经常导出表中部分数据。有时候导出titles可能有细微变化。由于TemplateInfo有很多属性,每次光复制粘贴TemplateInfo属性赋值那部分代码就够花时间的了,跟不用说让有点强迫症的人每次面对几乎差不多代码了。

      首先我们是不知道List<T>中T的具体类型,所以只能通过反射获取T的属性和值,在通过传递参数实现自定义,按照不同的参数条件,顺序,得到一组属性和对应值。然后直接生成文件。

     

    3.ReflectionUtil类,定义一组反射相关的方法

     1     public class ReflectionUtil
     2     {
     3         /// <summary>
     4         /// Get template public property name collection
     5         /// </summary>
     6         /// <param name="dateType">template type</param>
     7         /// <returns>property name collection</returns>
     8         public static List<string> GetPropertyNames<T>(T dateType)
     9         {
    10             if (dateType == null)
    11             {
    12                 throw new Exception("parameter cannot be null.");
    13             }
    14 
    15             var propertyName = new List<string>();
    16             Type type = dateType.GetType();
    17             PropertyInfo[] properties = type.GetProperties();
    18             foreach (var property in properties)
    19             {
    20                 propertyName.Add(property.Name.ToString());
    21             }
    22 
    23             return propertyName;
    24         }
    25 
    26         /// <summary>
    27         /// Get property adn set func
    28         /// </summary>
    29         /// <param name="dataType">template type</param>
    30         /// <param name="propertyName">property name</param>
    31         /// <returns></returns>
    32         public static Func<object, object> GetPropertySetFunc(Type dataType, string propertyName)
    33         {
    34             var propInfo = dataType.GetProperty(propertyName);
    35             var getMethodInfo = propInfo.GetGetMethod();
    36 
    37             DynamicMethod dynamicGet = CreateGetDynamicMethod(dataType);
    38             ILGenerator getGenerator = dynamicGet.GetILGenerator();
    39 
    40             getGenerator.Emit(OpCodes.Ldarg_0);
    41             getGenerator.Emit(OpCodes.Call, getMethodInfo);
    42             BoxIfNeeded(getMethodInfo.ReturnType, getGenerator);
    43             getGenerator.Emit(OpCodes.Ret);
    44 
    45             return dynamicGet.CreateDelegate(typeof(Func<object, object>)) as Func<object, object>;
    46         }
    47 
    48         /// <summary>
    49         /// Create get dynamic method
    50         /// </summary>
    51         /// <param name="type">template type</param>
    52         /// <returns></returns>
    53         private static DynamicMethod CreateGetDynamicMethod(Type type)
    54         {
    55             return new DynamicMethod("DynamicGet", typeof(object), new[] { typeof(object) }, type, true);
    56         }
    57 
    58         /// <summary>
    59         /// Box
    60         /// </summary>
    61         /// <param name="type">template type</param>
    62         /// <param name="generator">il generator</param>
    63         private static void BoxIfNeeded(Type type, ILGenerator generator)
    64         {
    65             if (type.IsValueType)
    66             {
    67                 generator.Emit(OpCodes.Box, type);
    68             }
    69         }
    70     }
    View Code

    4.CollectionExportUtil类,封装一组重载方法,根据不同参数满足各种文件需求导出。可以减少很多代码量和时间。

      1     /// <summary>
      2     /// ExportType can be add by new requirement in the future
      3     /// </summary>
      4     public enum ExportType
      5     {
      6         TxtFile,
      7         CsvFile,
      8         NoSeparator,
      9         Space,
     10         Other
     11     }
     12 
     13     public class CollectionExportUtil
     14     {
     15         /// <summary>
     16         /// export file from property index start
     17         /// </summary>
     18         /// <typeparam name="T">template</typeparam>
     19         /// <param name="dataCollection">template collection</param>
     20         /// <param name="propertyIndexStart">property index start</param>
     21         /// <param name="exportType">content type</param>
     22         /// <returns>content string</returns>
     23         public static string GenerateExportText<T>(List<T> dataCollection, int propertyIndexStart, ExportType exportType)
     24         {
     25             int propertyIndexEnd = ReflectionUtil.GetPropertyNames(dataCollection[0]).Count() - 1;
     26             return GenerateExportText(dataCollection, propertyIndexStart, propertyIndexEnd, exportType);
     27         }
     28 
     29         /// <summary>
     30         /// export file from property index start to index end
     31         /// </summary>
     32         /// <typeparam name="T">template</typeparam>
     33         /// <param name="dataCollection">template collection</param>
     34         /// <param name="propertyIndexStart">property index start</param>
     35         /// <param name="propertyIndexEnd">property index end </param>
     36         /// <param name="exportType">file type</param>
     37         /// <returns>content string</returns>
     38         public static string GenerateExportText<T>(List<T> dataCollection, int propertyIndexStart, int propertyIndexEnd, ExportType exportType)
     39         {
     40             if (propertyIndexStart == null || propertyIndexEnd == null)
     41             {
     42                 throw new Exception("property index parameter cannot be null.");
     43             }
     44 
     45             if (propertyIndexStart.CompareTo(0) < 0)
     46             {
     47                 throw new Exception("property index start must more than zero.");
     48             }
     49 
     50             if (propertyIndexStart.CompareTo(propertyIndexEnd) > 0)
     51             {
     52                 throw new Exception("property index start must less than index end.");
     53             }
     54 
     55             Dictionary<string, string> columnInfos = new Dictionary<string, string>();
     56             var columns = ReflectionUtil.GetPropertyNames(dataCollection[0]);
     57 
     58             if (propertyIndexEnd.CompareTo(columns.Count) > 0)
     59             {
     60                 throw new Exception("index end cannot bigger than column count.");
     61             }
     62 
     63             for (int i = propertyIndexStart; i <= propertyIndexEnd; i++)
     64             {
     65                 columnInfos.Add(columns[i], columns[i]);
     66             }
     67 
     68             return GenerateExportText(dataCollection, columnInfos, exportType);
     69         }
     70 
     71         /// <summary>
     72         /// Export by template property index list with property name
     73         /// </summary>
     74         /// <typeparam name="T">template</typeparam>
     75         /// <param name="dataCollection">template collection</param>
     76         /// <param name="indexs">property index with sequence </param>
     77         /// <param name="separator">separator</param>
     78         /// <returns>content string</returns>
     79         public static string GenerateExportText<T>(List<T> dataCollection, List<int> indexs, ExportType exportType)
     80         {
     81             if (indexs == null)
     82             {
     83                 throw new Exception("parameter cannot be null.");
     84             }
     85 
     86             Dictionary<string, string> columnInfos = new Dictionary<string, string>();
     87             var columns = ReflectionUtil.GetPropertyNames(dataCollection[0]);
     88             for (int i = 0; i < indexs.Count; i++)
     89             {
     90                 columnInfos.Add(columns[indexs[i]], columns[indexs[i]]);
     91             }
     92 
     93             return GenerateExportText(dataCollection, columnInfos, exportType);
     94         }
     95 
     96         /// <summary>
     97         /// Export by template property index list with sequence
     98         /// </summary>
     99         /// <typeparam name="T">template</typeparam>
    100         /// <param name="dataCollection">template collection</param>
    101         /// <param name="indexs">property index with sequence </param>
    102         /// <param name="titles">title of the property with sequence</param>
    103         /// <param name="separator">separator</param>
    104         /// <returns>content string</returns>
    105         public static string GenerateExportText<T>(List<T> dataCollection, List<int> indexs, List<string> titles, ExportType exportType)
    106         {
    107             if (indexs == null || titles == null)
    108             {
    109                 throw new Exception("parameter cannot be null.");
    110             }
    111 
    112             if (indexs.Count != titles.Count)
    113             {
    114                 throw new Exception("index count not equal the titles count.");
    115             }
    116 
    117             Dictionary<string, string> columnInfos = new Dictionary<string, string>();
    118             var columns = ReflectionUtil.GetPropertyNames(typeof(T));
    119             for (int i = 0; i < indexs.Count; i++)
    120             {
    121                 columnInfos.Add(titles[i], columns[indexs[i]]);
    122             }
    123 
    124             return GenerateExportText(dataCollection, columnInfos, exportType);
    125         }
    126 
    127         /// <summary>
    128         /// Export by template with all property name as the titles
    129         /// </summary>
    130         /// <typeparam name="T">template</typeparam>
    131         /// <param name="dataCollection">template collection</param>
    132         /// <param name="separator">separator</param>
    133         /// <returns>content string</returns>
    134         public static string GenerateExportText<T>(List<T> dataCollection, ExportType exportType)
    135         {
    136             Dictionary<string, string> columnInfos = new Dictionary<string, string>();
    137             var columns = ReflectionUtil.GetPropertyNames(dataCollection[0]);
    138             foreach (var item in columns)
    139             {
    140                 columnInfos.Add(item, item);
    141             }
    142 
    143             return GenerateExportText(dataCollection, columnInfos, exportType);
    144         }
    145 
    146         /// <summary>
    147         /// Export by template with (title,property)
    148         /// </summary>
    149         /// <typeparam name="T">template</typeparam>
    150         /// <param name="dataCollection">template collection</param>
    151         /// <param name="columnInfos">(title,property) collection</param>
    152         /// <param name="separator">separator</param>
    153         /// <returns>content string</returns>
    154         public static string GenerateExportText<T>(List<T> dataCollection, Dictionary<string, string> columnInfos, ExportType exportType)
    155         {
    156             StringBuilder fullText = new StringBuilder();
    157             var headers = columnInfos.Select(p => p.Key);
    158 
    159             string separator = string.Empty;
    160             switch (exportType)
    161             {
    162                 case ExportType.TxtFile:
    163                     separator = "	";
    164                     break;
    165                 case ExportType.CsvFile:
    166                     separator = ",";
    167                     break;
    168                 case ExportType.NoSeparator:
    169                     separator = "";
    170                     break;
    171                 case ExportType.Space:
    172                     separator = " ";
    173                     break;
    174             }
    175 
    176             //add title
    177             fullText.AppendLine(string.Join(separator, headers));
    178 
    179             if (dataCollection == null)
    180             {
    181                 return fullText.ToString();
    182             }
    183 
    184             Dictionary<string, Func<object, object>> delegateMap = new Dictionary<string, Func<object, object>>();
    185             Type dataType = typeof(T);
    186 
    187             foreach (var pair in columnInfos)
    188             {
    189                 string propertyName = pair.Value;
    190                 delegateMap.Add(propertyName, ReflectionUtil.GetPropertySetFunc(dataType, propertyName));
    191             }
    192 
    193             foreach (var data in dataCollection)
    194             {
    195                 List<string> values = new List<string>();
    196 
    197                 foreach (var pair in columnInfos)
    198                 {
    199                     string propertyName = pair.Value;
    200                     var getValueFunc = delegateMap[propertyName];
    201                     values.Add(getValueFunc.Invoke(data).ToString());
    202                 }
    203 
    204                 //add value
    205                 fullText.AppendLine(string.Join(separator, values));
    206             }
    207 
    208             return fullText.ToString();
    209         }
    210 
    211         /// <summary>
    212         /// genetate file
    213         /// </summary>
    214         /// <param name="content"></param>
    215         /// <param name="path"></param>
    216         public static void GenerateExportFile(string content, string path)
    217         {
    218             File.WriteAllText(path, content, Encoding.Default);
    219         }
    220 
    221         /// <summary>
    222         /// generate file with encoding type
    223         /// </summary>
    224         /// <param name="content"></param>
    225         /// <param name="path"></param>
    226         /// <param name="encoding"></param>
    227         public static void GenerateExportFile(string content, string path, Encoding encoding)
    228         {
    229             if ((path + "").Trim().Length == 0)
    230             {
    231                 throw new Exception("path of generated cannot be empty.");
    232             }
    233 
    234             if (!Directory.Exists(Path.GetDirectoryName(path)))
    235             {
    236                 Directory.CreateDirectory(Path.GetDirectoryName(path));
    237             }
    238 
    239             File.WriteAllText(path, content, encoding);
    240         }
    241     }
    View Code

    5.使用举例:Demon

      5.1 对于表:AutoDivInsertBulkLoaderInfo

      1     public class AutoDivInsertBulkLoaderInfo
      2     {
      3         public string RicEventType { get; set; }//key of the table}
      4         public string URL { get; set; }
      5         public string AnnualOrSemiAnnualReport { get; set; }
      6         public string RIC { get; set; }
      7         public string DVP_TYPE { get; set; }
      8         public string CLA_EVENT_STATUS { get; set; }
      9         public string FPE_PERIOD_END { get; set; }
     10         public string FPE_PERIOD_LENGTH { get; set; }
     11         public string DIVIDEND_AMOUNT { get; set; }
     12         public string ANNOUNCEMENT_DATE { get; set; }
     13         public string PAY_DATE { get; set; }
     14         public string RECORD_DATE { get; set; }
     15         public string EX_DATE { get; set; }
     16         public string PAYDATE_DAY_SET { get; set; }
     17         public string PAID_AS_PERCENT { get; set; }
     18         public string CLA_CUR_VAL { get; set; }
     19         public string QDI_PERCENT { get; set; }
     20         public string DESCRIPTION { get; set; }
     21         public string CLA_MEETING_TYPE_VAL { get; set; }
     22         public string MEETING_DATE { get; set; }
     23         public string CLA_TAX_STATUS_VAL { get; set; }
     24         public string TAX_RATE_PERCENT { get; set; }
     25         public string FOREIGN_INVESTOR_TAX_RATE { get; set; }
     26         public string SOURCE_TYPE { get; set; }
     27         public string RELEASE_DATE { get; set; }
     28         public string LOCAL_DATE { get; set; }
     29         public string TIMEZONE_NAME { get; set; }
     30         public string SOURCE_PROVIDER { get; set; }
     31         public string BRIDGE_SYMBOL { get; set; }
     32         public string SEQ_NUM { get; set; }
     33         public string CLA_RECORD_STATUS { get; set; }
     34         public string FPE_PERIOD_LENGTH_INDICATOR { get; set; }
     35         public string CLA_DIV_MARKER_VAL { get; set; }
     36         public string CLA_DIV_FREQ_VAL { get; set; }
     37         public string PID_QUARTER { get; set; }
     38         public string PID_YEAR { get; set; }
     39         public string PID { get; set; }
     40         public string CLA_TEXT_TYPE { get; set; }
     41         public string CLA_DIV_FEATURES_VAL { get; set; }
     42         public string TAX_CREDIT_PERCENT { get; set; }
     43         public string CLA_TAX_TRTMNT_MKR_VAL { get; set; }
     44         public string RESCINDED { get; set; }
     45         public string CAC_MA_COMMENTS { get; set; }
     46         public string FRANKED_PERCENT { get; set; }
     47         public string REINVESTMENT_PLAN_AVAILABLE { get; set; }
     48         public string REINVESTMENT_DEADLINE { get; set; }
     49         public string REINVESTMENT_PRICE { get; set; }
     50         public string CLA_SOURCE_OF_FUND { get; set; }
     51         public string CLA_DIV_RANKING { get; set; }
     52         public string DIVIDEND_RANKING_DATE { get; set; }
     53         public string BOOKCLOSURE_START_DATE { get; set; }
     54         public string BOOKCLOSURE_END_DATE { get; set; }
     55         public string MODIFIED { get; set; }
     56         public string SOURCE_ID { get; set; }
     57         public string SOURCE_LINK { get; set; }
     58         public string SOURCE_DESCRIPTION { get; set; }
     59 
     60         public AutoDivInsertBulkLoaderInfo()
     61         {
     62             //this.RicEventType = string.Empty;//key
     63             this.URL = string.Empty;
     64             this.AnnualOrSemiAnnualReport = string.Empty;
     65             //this.RIC = string.Empty;
     66             //this.DVP_TYPE = string.Empty;
     67             this.CLA_EVENT_STATUS = string.Empty;
     68             this.FPE_PERIOD_END = string.Empty;
     69             this.FPE_PERIOD_LENGTH = string.Empty;
     70             this.DIVIDEND_AMOUNT = string.Empty;
     71             this.ANNOUNCEMENT_DATE = string.Empty;
     72             this.PAY_DATE = string.Empty;
     73             this.RECORD_DATE = string.Empty;
     74             this.EX_DATE = string.Empty;
     75             this.PAYDATE_DAY_SET = string.Empty;
     76             this.PAID_AS_PERCENT = string.Empty;
     77             this.CLA_CUR_VAL = string.Empty;
     78             this.QDI_PERCENT = string.Empty;
     79             this.DESCRIPTION = string.Empty;
     80             this.CLA_MEETING_TYPE_VAL = string.Empty;
     81             this.MEETING_DATE = string.Empty;
     82             this.CLA_TAX_STATUS_VAL = string.Empty;
     83             this.TAX_RATE_PERCENT = string.Empty;
     84             this.FOREIGN_INVESTOR_TAX_RATE = string.Empty;
     85             this.SOURCE_TYPE = string.Empty;
     86             this.RELEASE_DATE = string.Empty;
     87             this.LOCAL_DATE = string.Empty;
     88             this.TIMEZONE_NAME = string.Empty;
     89             this.SOURCE_PROVIDER = string.Empty;
     90             this.BRIDGE_SYMBOL = string.Empty;
     91             this.SEQ_NUM = string.Empty;
     92             this.CLA_RECORD_STATUS = string.Empty;
     93             this.FPE_PERIOD_LENGTH_INDICATOR = string.Empty;
     94             this.CLA_DIV_MARKER_VAL = string.Empty;
     95             this.CLA_DIV_FREQ_VAL = string.Empty;
     96             this.PID_QUARTER = string.Empty;
     97             this.PID_YEAR = string.Empty;
     98             this.PID = string.Empty;
     99             this.CLA_TEXT_TYPE = string.Empty;
    100             this.CLA_DIV_FEATURES_VAL = string.Empty;
    101             this.TAX_CREDIT_PERCENT = string.Empty;
    102             this.CLA_TAX_TRTMNT_MKR_VAL = string.Empty;
    103             this.RESCINDED = string.Empty;
    104             this.CAC_MA_COMMENTS = string.Empty;
    105             this.FRANKED_PERCENT = string.Empty;
    106             this.REINVESTMENT_PLAN_AVAILABLE = string.Empty;
    107             this.REINVESTMENT_DEADLINE = string.Empty;
    108             this.REINVESTMENT_PRICE = string.Empty;
    109             this.CLA_SOURCE_OF_FUND = string.Empty;
    110             this.CLA_DIV_RANKING = string.Empty;
    111             this.DIVIDEND_RANKING_DATE = string.Empty;
    112             this.BOOKCLOSURE_START_DATE = string.Empty;
    113             this.BOOKCLOSURE_END_DATE = string.Empty;
    114             this.MODIFIED = string.Empty;
    115             this.SOURCE_ID = string.Empty;
    116             this.SOURCE_LINK = string.Empty;
    117             this.SOURCE_DESCRIPTION = string.Empty;
    118         }
    119     }
    View Code

      5.2 需求导出从URL开始(第2个属性)按升顺方式将AutoDivInsertBulkLoaderInfo所有属性的值导出,且属性AnnualOrSemiAnnualReport的Title改为

      ”Annual/Semi-annual Report“,其他Title 等于默认属性名。

     1         private void GenerateAutoDivInsertBulkLoaderBulkFile(List<AutoDivInsertBulkLoaderInfo> autoinsertBulkFile)
     2         {
     3             if (autoinsertBulkFile == null || autoinsertBulkFile.Count == 0)
     4             {
     5                 Logger.Log("autoinsertBulkFile collection is empty, neednot to generate autoinsertBulkFile.csv file.", Logger.LogType.Warning);
     6                 return;
     7             }
     8 
     9             Dictionary<string, string> titles = new Dictionary<string, string>();
    10             var property = Ric.Util.ReflectionUtil.GetPropertyNames(autoinsertBulkFile[0]);
    11             for (int i = 0; i < property.Count; i++)
    12             {
    13                 if (i == 0)
    14                     continue;
    15 
    16                 if (i == 2)
    17                     titles.Add("Annual/Semi-annual Report", property[i]);
    18                 else
    19                     titles.Add(property[i], property[i]);
    20             }
    21 
    22             string path = Path.Combine(resultPath, DateTime.Now.ToString("dd-MM-yyyy"));
    23             string fileName = Path.Combine(path, string.Format("AUTO_DIV_Insert_Bulk_Loader_{0}.csv", DateTime.Now.ToString("dd-MM-yyyy")));
    24             CollectionExportUtil.GenerateExportFile(CollectionExportUtil.GenerateExportText(autoinsertBulkFile, titles, ExportType.CsvFile), fileName);
    25         }
    View Code
  • 相关阅读:
    LeetCode 230. 二叉搜索树中第K小的元素(Kth Smallest Element in a BST)
    LeetCode 216. 组合总和 III(Combination Sum III)
    LeetCode 179. 最大数(Largest Number)
    LeetCode 199. 二叉树的右视图(Binary Tree Right Side View)
    LeetCode 114. 二叉树展开为链表(Flatten Binary Tree to Linked List)
    LeetCode 106. 从中序与后序遍历序列构造二叉树(Construct Binary Tree from Inorder and Postorder Traversal)
    指针变量、普通变量、内存和地址的全面对比
    MiZ702学习笔记8——让MiZ702变身PC的方法
    你可能不知道的,定义,声明,初始化
    原创zynq文章整理(MiZ702教程+例程)
  • 原文地址:https://www.cnblogs.com/HaifengCai/p/4000314.html
Copyright © 2011-2022 走看看