在 C# 中获取属性值(反射)的最快方法

2024-01-01

我想知道从对象的属性获取值(仅针对此问题)的最快方法是什么?

经过一番搜索后,我在这个网站上看到了 @MarkGravell 的帖子

他写了这段代码:

using System;
using System.Reflection;
using System.Reflection.Emit;

public class Foo
{
    public Foo(int bar)
    {
        Bar = bar;
    }
    private int Bar { get; set; }
}
static class Program {
    static void Main()
    {
        var method = new DynamicMethod("cheat", typeof(int),
            new[] { typeof(object) }, typeof(Foo), true);
        var il = method.GetILGenerator();
        il.Emit(OpCodes.Ldarg_0);
        il.Emit(OpCodes.Castclass, typeof(Foo));
        il.Emit(OpCodes.Callvirt, typeof(Foo).GetProperty("Bar",
            BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
            ).GetGetMethod(true));
        il.Emit(OpCodes.Ret);
        var func = (Func<object, int>)method.CreateDelegate(
            typeof(Func<object, int>));

        var obj = new Foo(123);
        Console.WriteLine(func(obj));
    }
}

OR

var method = typeof(Foo).GetProperty("Bar",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                                                  .GetGetMethod(true);
var func = (Func<Foo, int>)
Delegate.CreateDelegate(typeof(Func<Foo, int>), method);

我把它改为

var pt = propertyInfo.PropertyType; // I dont know what is Type
var method = pt.GetProperty("Bar",
    BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                                                      .GetGetMethod(true);
var func = (Func<Foo, object>) // I dont know what is return type so set object !!!
Delegate.CreateDelegate(typeof(Func<Foo, object>), method); // I want get value as object ?!!!
return func(entity).ToString(); // cast return value to string

但我有一个例外

 Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.

我不知道我的属性类型是什么 它可以是任何类型 如何为此目的自定义代码?

如果有人可以在没有财产类型限制的情况下以更好的方式(最快的方式)帮助我,请介绍一下


The Delegate.CreateDelegate在这种情况下不起作用,因为您必须将结果委托转换为某种已知类型,否则您所拥有的就是DynamicInvoke这并不比直接调用更好PropertyInfo (see here https://stackoverflow.com/questions/12858340/difference-between-invoke-and-dynamicinvoke马克·格拉维尔 (Marc Gravell) 的解释)。

我见过的最通用的方法不涉及 lambda 表达式(例如 Sriram Sakthivel 建议)由 Jon Skeet 展示here http://codeblog.jonskeet.uk/2008/08/09/making-reflection-fly-and-exploring-delegates/comment-page-1/。基于他的方法以及我们可以从中获取实际属性返回类型的事实PropertyInfo,我们可以为属性调用发明一些定制的东西。

首先,我们定义一个接口:

public interface IPropertyCallAdapter<TThis>
{
    object InvokeGet(TThis @this);
    //add void InvokeSet(TThis @this, object value) if necessary
}

然后,该接口的实现:

public class PropertyCallAdapter<TThis, TResult> : IPropertyCallAdapter<TThis>
{
    private readonly Func<TThis, TResult> _getterInvocation;

    public PropertyCallAdapter(Func<TThis, TResult> getterInvocation)
    {
        _getterInvocation = getterInvocation;
    }

    public object InvokeGet(TThis @this)
    {
        return _getterInvocation.Invoke(@this);
    }
}

The InvokeGet方法看起来很像 Jon Skeet 使用的方法。

现在,到“神奇”的部分。我们定义一个服务,它将构建并缓存提供者的实例。它看起来像这样:

public class PropertyCallAdapterProvider<TThis>
{
    private static readonly Dictionary<string, IPropertyCallAdapter<TThis>> _instances =
        new Dictionary<string,IPropertyCallAdapter<TThis>>();

    public static IPropertyCallAdapter<TThis> GetInstance(string forPropertyName)
    {
        IPropertyCallAdapter<TThis> instance;
        if (!_instances.TryGetValue(forPropertyName, out instance))
        {
            var property = typeof(TThis).GetProperty(
                forPropertyName,
                BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

            MethodInfo getMethod;
            Delegate getterInvocation = null;
            if (property != null && (getMethod = property.GetGetMethod(true)) != null)
            {
                var openGetterType = typeof(Func<,>);
                var concreteGetterType = openGetterType
                    .MakeGenericType(typeof(TThis), property.PropertyType);

                getterInvocation =
                    Delegate.CreateDelegate(concreteGetterType, null, getMethod);
            }
            else
            {
                //throw exception or create a default getterInvocation returning null
            }

            var openAdapterType = typeof(PropertyCallAdapter<,>);
            var concreteAdapterType = openAdapterType
                .MakeGenericType(typeof(TThis), property.PropertyType);
            instance = Activator
                .CreateInstance(concreteAdapterType, getterInvocation)
                    as IPropertyCallAdapter<TThis>;

            _instances.Add(forPropertyName, instance);
        }

        return instance;
    }
}

在这里,在编译时不知道确切的TResult类型,我们创建适配器并将其缓存以供后续使用,以防止将来出现大量反射调用。

就是这样。您可以通过以下方式使用它:

PropertyCallAdapterProvider<Foo>.GetInstance("Bar").InvokeGet(fooInstance)

此外,如果需要,您可以轻松地将其扩展到属性设置器。

在我的机器上,这些是在进入循环之前从提供者预取适配器实例时使用各种方法访问循环中的 getter 一千万次的结果:

  • 直接调用 141 毫秒
  • 适配器调用 244 毫秒
  • 反射调用 1800 毫秒
  • 动态委托调用需要 8179 毫秒
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 C# 中获取属性值(反射)的最快方法 的相关文章

  • 每个托管线程是否都有自己对应的本机线程?

    我想知道是否在 Net 中创建托管线程 通过调用Thread Start 导致在后台创建一个本机线程 那么托管线程是否有对应的本机线程呢 如果是 当托管线程等待或睡眠时 是否意味着相应的本机线程也在等待或睡眠 是的 NET 线程映射到所有当
  • 未提供参数时如何指定 C# System.Commandline 行为?

    在我的控制台应用程序中 当未提供控制台参数时 将执行我指定列表 在本例中为参数 3 的任何处理程序 调用该处理程序时 布尔参数设置为 false 但对我来说 根本不调用它更有意义 如何防止这种情况发生并显示帮助文本 using System
  • Directory.Delete 之后 Directory.Exists 有时返回 true ?

    我有非常奇怪的行为 我有 Directory Delete tempFolder true if Directory Exists tempFolder 有时 Directory Exists 返回 true 为什么 可能是资源管理器打开了
  • 如何将非静态类成员“std::bind”绑定到 Win32 回调函数“WNDPROC”?

    我正在尝试将非静态类成员绑定到标准WNDPROC http msdn microsoft com en us library ms633573 aspx功能 我知道我可以通过将类成员设为静态来简单地做到这一点 但是 作为一名 C 11 ST
  • 计算 Richtextbox 中所有单词的最有效方法是什么?

    我正在编写一个文本编辑器 需要提供实时字数统计 现在我正在使用这个扩展方法 public static int WordCount this string s s s TrimEnd if String IsNullOrEmpty s re
  • 提交后禁用按钮

    当用户提交付款表单并且发布表单的代码导致 Firefox 中出现重复发布时 我试图禁用按钮 去掉代码就不会出现这个问题 在firefox以外的任何浏览器中也不会出现这个问题 知道如何防止双重帖子吗 System Text StringBui
  • 在 C 中匹配二进制模式

    我目前正在开发一个 C 程序 需要解析一些定制的数据结构 幸运的是我知道它们是如何构造的 但是我不确定如何在 C 中实现我的解析器 每个结构的长度都是 32 位 并且每个结构都可以通过其二进制签名来识别 举个例子 有两个我感兴趣的特定结构
  • 单个对象的 Monogame XNA 变换矩阵?

    我读过一些解释 XNA Monogame 变换矩阵的教程 问题是这些矩阵应用于 SpriteBatch Begin matrix 这意味着所有 Draw 代码都将被转换 如何将变换矩阵应用于单个可绘制对象 就我而言 我想转换滚动背景 使其自
  • qdbusxml2cpp 未知类型

    在使用 qdbusxml2cpp 程序将以下 xml 转换为 Qt 类时 我收到此错误 qdbusxml2cpp c ObjectManager a ObjectManager ObjectManager cpp xml object ma
  • 为什么调用非 const 成员函数而不是 const 成员函数?

    为了我的目的 我尝试包装一些类似于 Qt 共享数据指针的东西 经过测试 我发现当应该调用 const 函数时 会选择它的非 const 版本 我正在使用 C 0x 选项进行编译 这是一个最小的代码 struct Data int x con
  • 使用自定义堆的类似 malloc 的函数

    如果我希望使用自定义预分配堆构造类似 malloc 的功能 那么 C 中最好的方法是什么 我的具体问题是 我有一个可映射 类似内存 的设备 已将其放入我的地址空间中 但我需要获得一种更灵活的方式来使用该内存来存储将随着时间的推移分配和释放的
  • Azure 辅助角色“请求输入之一超出范围”的内部异常。

    我在辅助角色中调用 CloudTableClient CreateTableIfNotExist 方法 但收到一个异常 其中包含 请求输入之一超出范围 的内部异常 我做了一些研究 发现这是由于将表命名为非法表名引起的 但是 我尝试为我的表命
  • 外键与独立关系 - Entity Framework 5 有改进吗?

    我读过了several http www ladislavmrnka com 2011 05 foreign key vs independent associations in ef 4 文章和问题 https stackoverflow
  • 等待进程释放文件

    我如何等待文件空闲以便ss Save 可以用新的覆盖它吗 如果我紧密地运行两次 左右 我会得到一个generic GDI error
  • AES 128 CBC 蒙特卡罗测试

    我正在 AES 128 CBC 上执行 MCT 如中所述http csrc nist gov groups STM cavp documents aes AESAVS pdf http csrc nist gov groups STM ca
  • “接口”类似于 boost::bind 的语义

    我希望能够将 Java 的接口语义与 C 结合起来 起初 我用过boost signal为给定事件回调显式注册的成员函数 这非常有效 但后来我发现一些函数回调池是相关的 因此将它们抽象出来并立即注册所有实例的相关回调是有意义的 但我了解到的
  • 按 Esc 按键关闭 Ajax Modal 弹出窗口

    我已经使用 Ajax 显示了一个面板弹出窗口 我要做的是当用户按 Esc 键时关闭该窗口 这可能吗 如果有人知道这一点或以前做过这一点 请帮助我 Thanks 通过以下链接 您可以通过按退出按钮轻松关闭窗口 http www codepro
  • System.IO.FileNotFoundException:找不到网络路径。在 Windows 7 上使用 DirectoryEntry 对象时出现异常

    我正在尝试使用 DirectoryEntry 对象连接到远程 Windows 7 计算机 这是我的代码 DirectoryEntry obDirEntry new DirectoryEntry WinNT hostName hostName
  • Oracle Data Provider for .NET 不支持 Oracle 19.0.48.0.0

    我们刚刚升级到 Oracle 19c 19 3 0 所有应用程序都停止工作并出现以下错误消息 Oracle Data Provider for NET 不支持 Oracle 19 0 48 0 0 我将 Oracle ManagedData
  • 从列表中选择项目以求和

    我有一个包含数值的项目列表 我需要使用这些项目求和 我需要你的帮助来构建这样的算法 下面是一个用 C 编写的示例 描述了我的问题 int sum 21 List

随机推荐

  • HttpRuntime 缓存与静态字典/字段

    主要有哪些pros and cons使用 HttpRuntime Cache 反对使用简单的静态字段 我需要在整个 ASP NET 应用程序范围内存储数据 HttpRuntime Cache MyData someHashtable vs
  • 用于提高性能的代码分析:查看 mscorlib.dll 内的 CPU 周期?

    我做了一个小型测试基准来比较 NETSystem Security CryptographyAES 实现与 BouncyCastle Org 的 AES 对比 GitHub 代码链接 https github com sidshetye B
  • clojure.xml/emit 发生了什么?

    许多博客都提到了 clojure xml emit 或 clojure contrib lazy xml emit 函数 但 1 2 文档中似乎没有它 它被弃用了吗 什么取代了它 它可以用来编写 Clojure 编码的 XML 例如 tag
  • Django Forms DateInput 小部件未填充

    我有一个 django 编辑表单 其中包含模型中的许多字段 包括一些日期字段 为了获得合适的格式 我使用了 DateInput 小部件 不幸的是 当我们编辑对象时 所有其他字段都已经填充了现有数据 但日期除外 日期处于其初始状态 dd mm
  • 如何在anaconda中安装包?

    我想将音乐包添加到 anaconda 解释器中 我使用的是 ubuntu 14 04 64 位 我从anaconda云下载了music21 1 9 3 tar gz 我将其解压到 anaconda3 pkgs ext installer p
  • 将日期输入类型默认值设置为今天、明天、任意日期?

    在 HTML5 中 没有在 value 属性中指定 今天 的本机方法 这是我非常喜欢的 jQuery 代码 如何扩展此代码来设置 今天的日期到var today 明天的日期到var tomorrow 计算得出的任何日期var anydate
  • 如何在java中创建枚举对象

    我试图定义枚举类 Item 的三个不同对象 其权重在 0 到 20 之间以及每个项目的描述 这是我的代码 public enum Item Three Items with descriptions GOLD 2 gold SILVER 1
  • 如何使用Java中的文件中的特定行号读取特定行?

    在Java中 有什么方法可以从文件中读取特定行吗 例如 读取第 32 行或任何其他行号 对于小文件 String line32 Files readAllLines Paths get file txt get 32 对于大文件 try S
  • 如何在AWS EMR上重新启动yarn

    我正在使用 Hadoop 2 6 0 emr 4 2 0图像 我做了一些改变yarn site xml并希望重新启动纱线以使更改生效 有一个命令可以用来执行此操作吗 编辑 2017 年 10 月 26 日 AWS 官方已在此处发布了有关如何
  • Angular 5(Karma / Jasmine 测试)- 使用模拟后端来模拟错误消息的错误响应

    我不太明白 MockBackend 功能是如何工作的描述在这里 https angular io api http testing MockBackend 我对 Angular 完全陌生 我想编写一些测试用例 以确保当后端发生服务器错误时
  • 用于平铺渲染的 OpenGL 矩阵设置

    看完之后datenwolf 2011 年关于 OpenGL 中基于图块的渲染设置的回答 https stackoverflow com questions 6490728 capture snapshot of opengl window
  • 使用 Monkey Test 时如何防止输入设置

    我在 Android 设备 LG G4 中对我的应用程序进行了猴子测试 命令是 adb shell monkey p package name v 2000 但它可能会意外进入设置并更改我的设备的默认值 如何预防呢 Monkey支持黑名单
  • 使用 KVO 更改属性时发送通知

    我有一个名为myName在我的课堂上 比如 property nonatomic strong NSString myName 我需要在以下情况时发送通知myName属性的值发生改变 现在我正在做类似的事情 void setMyName N
  • 如何在设计时进行调试?

    我使用 UserControl 创建了一个自定义 ListView 当鼠标进入 ColumnHeader 时 它应该在设计时改变颜色 它有效 但我需要调试代码 如何在设计时调试代码 See 演练 在设计时调试自定义 Windows 窗体控件
  • 可以删除Android依赖吗?

    我有一个应用程序 到目前为止一直工作和编译得很好 但是 当我转到 导出 时 会自动添加 Android 依赖项 这会引发 转换为 Dalvik 格式失败 错误 1 我对此进行了研究 我知道这是因为 Android 依赖项添加了重复文件 我目
  • 加入具有不同排序规则问题的列

    我正在使用 SQL Server 2005 我有两个表 它们使用不同的排序规则 不允许连接具有不同排序规则的表中的列 例如不允许使用以下 SQL select table1column1 table2column2 from 我的问题是 为
  • C++/SDL2——渲染一个圆[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我用 SDL2 画一个实心圆 方向正确吗 我认为使用参数方程和趋于零的半径是可行的 但在处理器使用方面似乎效率很低 任何其他想法都非常感谢 提前
  • 如何从 Ruby on Rails 应用程序中的 OAuth::Unauthorized 异常中拯救出来?

    如何挽救 Ruby on Rails 应用程序中 OmniAuth 引发的 OAuth Unauthorized 异常 显然是这样的 rescue from OAuth Unauthorized with gt unauthorized 不
  • java nio 直接缓冲区上的压缩

    gzip 输入 输出流不在 Java 直接缓冲区上运行 是否有直接在直接缓冲区上运行的压缩算法实现 这样就不会产生将直接缓冲区复制到 java 字节数组进行压缩的开销 我无意转移你的问题 但这就是really你的程序中有一个好的优化点吗 您
  • 在 C# 中获取属性值(反射)的最快方法

    我想知道从对象的属性获取值 仅针对此问题 的最快方法是什么 经过一番搜索后 我在这个网站上看到了 MarkGravell 的帖子 他写了这段代码 using System using System Reflection using Syst