使用.NET';时对类型元数据进行内存化是否有效;s反射API

本文关键字:是否 内存 有效 反射 API 元数据 NET 使用 类型 | 更新日期: 2023-09-27 17:59:50

我知道过早优化是万恶之母。然而,我想知道以下哪种替代方案更有效:

  • 对同一类型的T多次调用typeof(T).GetProperties()
  • 将检索到的属性记忆为Dictionary<Type, PropertyInfo[]>

以下是我使用第一种方法编写的一些代码:

private static T MakeElement<T>(SqlDataReader reader) where T : class, new() {
    T element = new T();
    PropertyInfo[] properties = typeof(T).GetProperties(); // critical line
    foreach (PropertyInfo property in properties)
        property.SetValue(element, reader[property.Name], null);
    return element;
}
public static T RetrieveElement<T>() where T : class, new() {
    T element = null;
    actions.Add(delegate(SqlDataReader reader) {
        if (reader.Read())
            element = MakeElement<T>(reader);
    });
    Execute();
    return element;
}
public static List<T> RetrieveList<T>() where T : class, new() {
    List<T> list = new List<T>();
    actions.Add(delegate(SqlDataReader reader) {
        while (reader.Read())
            list.Add(MakeElement<T>(reader));
    });
    Execute();
    return list;
}
// For the sake of completeness, here is the Execute method.
public static void Execute() {
    SqlConnectionStringBuilder connStringBuilder = new SqlConnectionStringBuilder();
    connStringBuilder.DataSource     = DataSource;
    connStringBuilder.InitialCatalog = InitialCatalog;
    connStringBuilder.UserID         = UserID;
    connStringBuilder.Password       = Password;
    using (SqlConnection connection = new SqlConnection(connStringBuilder.ConnectionString))
    using (SqlCommand command = new SqlCommand(StoredProcedure, connection)) {
        command.CommandType = CommandType.StoredProcedure;
        SqlParameterCollection parameterCollection = command.Parameters;
        foreach (KeyValuePair<string, object> parameter in parameters)
            parameterCollection.AddWithValue(parameter.Key, parameter.Value);
        try {
            connection.Open();
            using (SqlDataReader reader = command.ExecuteReader())
                foreach (Action<SqlDataReader> action in actions) {
                    action(reader);
                    reader.NextResult();
                }
        }
        finally {
            parameters.Clear();
            actions.Clear();
        }
    }
}

我已经在思考哪种方法更有效:

用于直接调用GetProperties

  • 无论如何,元数据都在那里。它不必重建,只需检索即可

用于记忆:

  • 元数据的格式可能是C#应用程序无法直接理解的,因此GetProperties中可能涉及一些预处理
  • 元数据在那里,但PropertyInfo的数组不在,因此必须重建

附加问题:.NET的Reflection API使用数组而不是索引器来检索类型元数据,这有什么原因吗?

使用.NET';时对类型元数据进行内存化是否有效;s反射API

我认为基于Type来存储结果是可以的。您应该根据自己的情况进行衡量,但我的经验是,调用GetProperties或其他反射方法会带来性能损失。GetProperties的结果无论如何都不会在运行时更改。

甚至更好:

public static class Memoizer<T>
{
    public static readonly PropertyInfo[] Properties = typeof(T).GetProperties();
}

只需确保数组没有更改,或者将其封装在ReadOnlyCollection中即可。