【问题标题】:Getting custom attributes for properties in class and SetValue获取类和 SetValue 中属性的自定义属性
【发布时间】:2013-01-05 14:19:00
【问题描述】:

我只是想玩一些东西。我做了一种 OR/M 类型的映射器,因为我使用的是反射,所以性能很慢。我怎样才能加快速度或使用更好、更有效的方法?

我有一个带有命名参数的自定义属性并允许多个 然后我使用反射来:

  • 获取包含自定义属性装饰的属性
  • 对于找到的每个属性,获取自定义属性数据
  • 对于每个自定义属性数据,获取命名参数

然后我检查命名参数 memberinfo 名称以查看它是否与属性的相关命名参数匹配,如果匹配,它将获取为该命名参数设置的值,最后从 dataReader 读取该命名参数值的数据并使用 .SetValue 将从读取器读取的值设置为属性。

这是一些代码(以任何方式都不完整),希望有人能告诉我如何获得性能改进。 运行它 10,000 次(在此之前对 JIT excersize 进行初始调用等...)给了我这些平均时间:

3.79 毫秒

以手动方式进行(即从 DB 到 DTO 的硬编码映射):0.05ms

我知道这就像“另一个 OR/M” - 但它不完全是那样,它比什么都更适合我。

private T Populate<T>(IDataReader reader) where T : class, new()
{ 
   T val = new T();

            if (reader != null && !reader.IsClosed)
            {

                var propsWithSQLColumnNameAttributes = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static).Where(prop => Attribute.IsDefined(prop, typeof(SQLColumnNameAttribute)) && prop.CanWrite && prop.GetSetMethod() != null);

                foreach (var currentProperty in propsWithSQLColumnNameAttributes)
                {   
                    foreach (var currentAttributeForProperty in currentProperty.GetCustomAttributesData())
                    {
                        string currentAttribParamValue = null;
                        foreach (var currentNamedArgument in currentAttributeForProperty.NamedArguments)
                        {
                            if (String.Equals(currentNamedArgument.MemberInfo.Name, SQLColumnNameAttribute.PropertyNames.DataColumnNamePropertyName, StringComparison.OrdinalIgnoreCase))
                            {
                                currentAttribParamValue = currentNamedArgument.TypedValue.Value == null ? null : currentNamedArgument.TypedValue.Value.ToString();


                                if (reader.DoesFieldExist(currentAttribParamValue))
                                {
                                    var dbRecordValue = reader[currentAttribParamValue] == DBNull.Value ? null : reader[currentAttribParamValue];

                                    currentProperty.SetValue(val, dbRecordValue, null);
                                }
                                break;
                            }
                        }
                    }
                }
            }

            return val;
}

不是最好的代码,但无论如何,性能是这里的问题,想知道如何改进它,要么通过使用不同的反射方法,要么可能使用的排序和算法类型不正确

非常感谢 - 我希望这个问题有意义。

【问题讨论】:

  • 您是想获得成绩作为一项学术活动,还是真的关心成绩?我问,因为如果是后者,那么答案会很不一样;)
  • 谢谢乔希!我担心表现。我想让它尽可能快速和高效
  • 例如,您可以检查 dapperSqlfu 的存储库

标签: c# .net reflection


【解决方案1】:

看看这个页面http://www.codeproject.com/Articles/503527/Reflection-optimization-techniques,看看它是否对你有帮助。 它谈到了许多场景中的反射优化,一旦你想学习,这可能是一个很好的资源。

【讨论】:

  • 谢谢巴塔廖。它看起来很有趣,但仍然认为它可能有点过多的代码来提高性能。但我想有时你需要这样做。从阅读和获取想法来看,似乎我可能需要在相关类()和构造函数中创建一个缓存字典,找到有关自身的详细信息并将 propertyName 和属性参数值存储在某种字典中由于 T 未知,因此无法访问缓存
  • 如果我明白你在说什么。 T 可以称为 typeof(T),因此字典中的键可以是 Type。喜欢 Dictionay.
  • 感谢 batagliao - 很可能。那里的问题是,由于对象“Type”比其他一些类型的类更臃肿,它显然会消耗更多的内存(即使它多几个字节或其他)。正如你所知道的,我是那些对记忆力和表现力持批评态度的人之一。好的,我将如何创建/存储这个缓存?我的意思是它应该是一个静态字典还是应该放在一个适当的缓存引擎中。缓存引擎的缺点是需要进行更多的维护和管理(即使用 ASP.NET 缓存)。它还必须是 MT 安全的
  • 如果你正在制作类似库的东西,你应该在你的库中缓存你的反射缓存。当然,我会使用静态字典,MT 安全。缺点是它会随着类型的反映而不断增长,即使它们不再使用。因此,您可以编写一个缓存类来包装字典并管理项目的到期时间。但是如果你不介意过期,那就更简单了
  • 谢谢。我在想这个!我也将使用我认为的并发字典。让我们看看情况如何,如果我没有看到改进或情况变得更糟(我对此表示怀疑),我会稍后再发回。
猜你喜欢
  • 2011-03-18
  • 2019-05-20
  • 2010-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-19
  • 1970-01-01
相关资源
最近更新 更多