【问题标题】:Can my custom mapping using reflection be faster?使用反射的自定义映射可以更快吗?
【发布时间】:2013-11-29 21:54:33
【问题描述】:

我有以下方法将源对象映射到重复的目标对象。然而,只有标有特定属性的某些属性需要映射到新对象上。

我的映射器目前如下所示:

public static class BaseObjectExtensions
{
    private static readonly Dictionary<string, Attribute[]> AttributeCache = new Dictionary<string, Attribute[]>();
    private static readonly Dictionary<string, PropertyInfo[]> PropertyCache = new Dictionary<string, PropertyInfo[]>();

    public static void Map(this IBaseObject destination, IBaseObject source)
    {
        if (source == null)
        {
            return;
        }

        var t = source.GetType();
        PropertyInfo[] properties;
        lock (PropertyCache)
        {
            if (!PropertyCache.TryGetValue(t.FullName, out properties))
            {
                properties = t.GetProperties();
                PropertyCache.Add(t.FullName, properties);
            }
        }

        lock (AttributeCache)
        {
            foreach (PropertyInfo prop in properties)
            {
                Attribute[] attrs;
                string k = t.FullName + prop;
                if (!AttributeCache.TryGetValue(k, out attrs))
                {
                    attrs = Attribute.GetCustomAttributes(prop);
                    AttributeCache.Add(k, attrs);
                }

                if (attrs.OfType<DatabaseMap>().Any())
                {
                    prop.SetValue(destination, prop.GetValue(source));
                }
            }
        }
    }
}

此地图可以用于单个项目或项目集合。我注意到性能瓶颈,所以经过大量研究后,我在两个缓存中添加了。大型项目集合时间如下:

  • 无反射缓存:26.6 秒
  • 使用反射缓存 (ConcurrentDictionary):31 秒
  • 使用反射缓存(锁定):4 秒

加速是戏剧性的,但我认为它仍然可以更好。经过大量阅读后,我发现了 FastInvokeanother FastInvoke 之类的东西,但似乎无法将它们应用于我想要完成的事情。

我还能做些什么来加快速度吗?

【问题讨论】:

    标签: c# caching reflection orm mapping


    【解决方案1】:

    我认为为了获得最佳性能,您应该使用 Reflection.Emit 编译映射器,或者使用现有的之一:Emit mapper vs valueinjecter or automapper performance

    【讨论】:

    • 天哪,EmitMapper 速度很快!现在以毫秒为单位。
    【解决方案2】:

    你可以试试这个,

    而不是依次处理所有属性,然后检查您的属性是否存在 - 只需获取具有您的属性的属性:

    var props = from p in this.GetType().GetProperties()
                let attr = p.GetCustomAttributes(typeof(DatabaseMap), true)
                where attr.Length == 1
                select new { Property = p, Attribute = attr.First() as DatabaseMap};
    

    此时,您在对象中只有那些用您的属性标记的属性。

    【讨论】:

    • 我试过这个并删除了我的属性缓存。然后缓存上述操作的结果。速度提升从 4 秒提高到 1.4 秒左右。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    • 2015-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多