首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >PropertyInfo GetValue与表达式缓存GetValue

PropertyInfo GetValue与表达式缓存GetValue
EN

Code Review用户
提问于 2019-01-22 07:57:50
回答 1查看 877关注 0票数 1

我已经通过逻辑从PropertyInfo实现了GetValue和Expression,但是我确信有更好的方法来完成我所做的每一件事。如果您对此代码有任何反馈意见,我将不胜感激,因为它确实按照规范工作:

MyLogic

  • 异步非阻塞,它在添加缓存时不阻塞线程。
  • 字典键使用propertyInfo GetHash()
  • 如果字典缓存包含键,则使用编译器表达式函数,否则使用反射GetValue。

My Class

代码语言:javascript
运行
复制
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;

public class TestService
{
    private static Dictionary ExpressionCache = new Dictionary();

    public IEnumerable Execute(IEnumerable enums)
    {
        var expressionCache = (enums);
        var props = typeof(T).GetProperties();
        foreach (var e in enums)
        {
            foreach (var p in props)
            {
                var func = GetOrAddExpressionCache(p);
                var value = string.Empty;
                if (func == null)
                {
                    Debug.WriteLine("Use Reflection");
                    value = p.GetValue(e).ToString();
                }
                else
                {
                    Debug.WriteLine("Use Expression");
                    value = func(e);
                }
                yield return value;
            }
        }
    }

    private Func GetOrAddExpressionCache(PropertyInfo prop)
    {
        var key = prop.GetHashCode();
        if (ExpressionCache.ContainsKey(key))
        {
            var func = ExpressionCache[key] as Func;
            return func;
        }else{
            Task.Run(()=>AddExpressionCacheAsync(prop));
            return null;
        }
    }

    //Asynchronous nonblocking, which does not block a thread when adding a Cache
    private async Task AddExpressionCacheAsync(PropertyInfo propertyInfo)
    {
        var key = propertyInfo.GetHashCode();
        if (!ExpressionCache.ContainsKey(key))
        {
            var func = GetValueGetter(propertyInfo);
            ExpressionCache.Add(key, func);
        }
        await Task.Yield();
    }

    private static Func GetValueGetter(PropertyInfo propertyInfo)
    {
        var instance = Expression.Parameter(propertyInfo.DeclaringType);
        var property = Expression.Property(instance, propertyInfo);
        var toString = Expression.Call(property, "ToString", Type.EmptyTypes);
        return Expression.Lambda>(toString, instance).Compile();
    }
}

Demo

代码语言:javascript
运行
复制
class Program{
    public static void Main(string[] args){
        var data = new[] { new { Name = "Henry", Age = 25 } };
        for (int i = 0; i < 2; i++)
        {
            var service = new TestService();
            var result = service.Execute(data).ToArray();
        }
    }
}

/* Console :
        Use Reflection
        Use Reflection
        Use Expression
        Use Expression
*/
EN

回答 1

Code Review用户

回答已采纳

发布于 2019-01-23 11:05:33

问题

  • 基于反射和基于表达式的方法都没有考虑到null值(NullReferenceException)。
  • 它们也没有考虑到带有索引器的类型(TargetParameterCountException)。
  • 散列码不是唯一的标识符。不同的属性(和一般的对象)可以具有相同的哈希代码--这仅仅意味着它们可能是相等的。将prop.MetadataToken与它们在(prop.Module.ModuleVersionId)中声明的模块结合使用。
  • 异步编译表达式使它比需要的要复杂得多,而且这种复杂性没有得到适当的处理:
    • 不能保证编译将在处理下一个对象时完成。这可能导致同一属性的多个编译。那是在浪费工作。
    • 这些编译的结果被添加到一个Dictionary中,它不是线程安全的.在最好的情况下,添加一个已经存在的键将引发异常。在最坏的情况下,字典的内部状态将被破坏。
    • 这些例外情况并没有被抓住。在.NET Framework4.5之前,这可能会导致崩溃,而在4.5及更高版本中,可能仍然会发生崩溃,这取决于特定的设置。

其他改进

  • 为什么Execute要采取一系列的项目,而不是单一的项目?扁平化结果很容易(data.SelectMany(service.Execute)),“不平坦”不是--调用者必须计算出属性的数量,并且您必须编写一个方法将单个序列分割成子序列。
  • 不要执行ExpressionCache.ContainsKey(key) (后面跟着ExpressionCache[key] ),而是使用TryGetValue。这使您可以检查键的存在,并通过一次查找获得它的关联值。
  • 制作AddExpressionCacheAsync async没有任何意义。它没有做任何异步工作( await Task.Yield()是无用的)。您已经从Task.Run调用中调用了该方法,因此无论如何都会异步执行该方法。
  • GetValueGetter中,使用nameof(object.ToString)而不是"ToString"

可读性问题

  • 有些名字描述性不强:Execute -> GetPropertyValuesenums -> itemsfunc -> compiledExpressionGetValueGetter -> CompileGetValueExpression
  • 有几个缩写不能提高可读性:e -> itemprops -> propertiesp -> property
票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/211976

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档