代码之家  ›  专栏  ›  技术社区  ›  Philip Wallace

如何优化此代码?

  •  0
  • Philip Wallace  · 技术社区  · 15 年前

    我有一个方法,它本质上把一个数据表转换成一个我称之为“包”的对象列表。每个会话多次调用此代码,许多会话同时运行,有时有数千行。因此,我需要尽可能快地完成任务。我有一个XML文件,其中包含数据列到属性的映射。优化的主要方法是 ConvertRowToBag -传入的类型参数是派生自 BagBase .

    这是一段很长的代码,但是任何提示都会非常感谢。

    public class BagBase
    {
        /// <summary>
        /// Dictionary of properties and names
        /// </summary>
        private static Dictionary<string, PropertyInfo> propertyDictionary = new Dictionary<string, PropertyInfo>();
    
        /// <summary>
        /// Table of column/property mappings
        /// </summary>
        private static DataTable mappings = new DataTable("Mappings");
    
        /// <summary>
        /// Returns true if the map exists
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        private static bool MappingExists(string columnName, Type type)
        {
            DataRow [] rows = BagBase.mappings.Select(String.Format("Type = '{0}' and ColumnName = '{1}'", type.Name, columnName));
            return (rows != null && rows.Length > 0);
        }
    
        /// <summary>
        /// Converts the table to bags.
        /// </summary>
        /// <param name="table">The table.</param>
        /// <param name="outputType">Type of the output.</param>
        /// <returns></returns>
        protected static List<BagBase> ConvertTableToBags(DataTable table, Type outputType)
        {
            Trace.TraceInformation(String.Format("ConvertTableToBags : table={0} Type={1}", table.TableName, outputType.Name));
    
            // Create an empty list
            List<BagBase> result = new List<BagBase>();
    
            // Iterate through the rows
            foreach (DataRow row in table.Rows)
            {
                // Add to the list
                result.Add(ConvertRowToBag(outputType, row));
            }
    
            Trace.TraceInformation("ConvertTableToBags Finished.");
    
            return result;
        }
    
        /// <summary>
        /// Converts the row to bag.
        /// </summary>
        /// <param name="outputType">Type of the output.</param>
        /// <param name="row">The row.</param>
        /// <returns></returns>
        protected static BagBase ConvertRowToBag(Type outputType, DataRow row)
        {
            // Create an instance of the child class and store in the base
            BagBase bag = Activator.CreateInstance(outputType) as BagBase;
    
            // Iterate through the columns
            foreach (DataColumn column in row.Table.Columns)
            {
                // If this column has been mapped
                if (BagBase.MappingExists(column.ColumnName, outputType))
                {
                    PropertyInfo property;
    
                    string columnProperty = String.Format("{0}={1}", column.ColumnName, outputType.Name);
    
                    // Get the property as defined in the map
                    if (!propertyDictionary.ContainsKey(columnProperty))
                    {
                        // Get the property
                        property = outputType.GetProperty(BagBase.GetColumnMapping(column.ColumnName, outputType));
    
                        // Add the property to the dictionary
                        propertyDictionary.Add(columnProperty, property);
                    }
                    else
                    {
                        property = propertyDictionary[columnProperty];
                    }
    
                    if (property != null)
                    {
                        if (!row.IsNull(column))
                        {
                            // Set the value to the in the table
                            if (property.PropertyType.BaseType != null && property.PropertyType.BaseType == typeof(Enum))
                            {
                                if (column.DataType != typeof(String))
                                {
                                    property.SetValue(bag, Enum.ToObject(property.PropertyType, row[column]), null);
                                }
                                else
                                {
                                    property.SetValue(bag, Enum.ToObject(property.PropertyType, Convert.ToChar(row[column])), null);
                                }
                            }
                            else if (property.PropertyType == typeof(DateTime?))
                            {
                                property.SetValue(bag, (DateTime?)row[column], null);
                            }
                            else
                            {
                                property.SetValue(bag, Convert.ChangeType(row[column], property.PropertyType), null);
                            }
                        }
                        else // No nulls
                        {
                            if (column.DataType == typeof(String))
                            {
                                property.SetValue(bag, String.Empty, null);
                            }
                        }
    
                        // Generate the unique class.property name
                        string propertyKey = String.Format("{0}.{1}", outputType.Name, property.Name);
                        if (!columnCaptions.ContainsKey(propertyKey))
                        {
                            // Add to the caption map
                            columnCaptions.Add(propertyKey, column.Caption);
                        }
                    }
                }
                else
                {
                    // If this column isn't mapped, add it to Other information
                    if (bag.OtherInformation == null)
                    {
                        bag.OtherInformation = new Dictionary<string, string>();
                    }
    
                    bag.OtherInformation.Add(column.ColumnName, !row.IsNull(column) ? row[column].ToString() : String.Empty);
                }
            }
    
            return bag;
        }
    }
    
    2 回复  |  直到 15 年前
        1
  •  5
  •   Ben S    15 年前

    使用分析器。我们无法知道您的代码实际花费的时间最多。

    试图一行一行地优化是没有用的,很多人似乎不知道这一点。计算机总是在等待资源,有时是CPU或磁盘IO,通常是用户。要使任何一段代码更快,请使用分析器查找瓶颈,并努力使代码更快。

        2
  •  2
  •   flatline    15 年前

    除了“使用探查器”的一般建议之外,可能没有一个瓶颈,但是一系列缓慢的调用或者过程的结构正在创建不必要的迭代。一目了然:

    • 针对数据表的选择通常不会很好地执行。
    • 反射带来了很多开销,看起来您依赖它,但是如果您可以限制它的范围,您可能会获得更好的总体性能。