首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从BindingFlags获得PropertyInfo

从BindingFlags获得PropertyInfo
EN

Stack Overflow用户
提问于 2016-11-11 10:12:09
回答 2查看 1.8K关注 0票数 2

我有一个通过调用Type.GetProperty()获得的对象,我想知道用于检索它的绑定标志的组合。

当我检查调试器中的对象时,我可以看到它是一个System.Reflection.RuntimePropertyInfo,它有一个包含所需值的BindingFlags属性。但是,这似乎是一个内部类型,因为编译器不承认它是一个有效的数据类型。相反,它将Type.GetProperty()返回的值视为一个System.Reflection.PropertyInfo,非常有趣的是,该值不包含BindingFlags属性。

有人可以建议我可能添加到项目中的引用,以便编译器理解System.Reflection.RuntimePropertyInfo类型,或者可能是获得BindingFlags值的另一种方法吗?我想我可以保存调用Type.GetProperty()时使用的值,并将它与[Runtime]PropertyInfo对象一起携带到任何地方,但这看起来很难看。

我是(还在!)使用.NET框架3.5,如果这有帮助的话。谢谢!

编辑:

所有这些的上下文都是一个简单的表达式求解器,它允许我的用户访问有限的全局对象集及其一些属性,以便创建带有来自数据库的可变信息的自定义通知。在设计时,我的用户定义类似"Hello, [=Shipment.Recipient.Name]. Your order [=Shipment.Id] is ready for delivery."之类的内容,然后当通知呈现时,系统输出"Hello,Bob。您的订单12345已准备好交付“。

我考虑使用CodeProvider框架提供的.NET类,但我需要在没有安装Visual的中等信任环境中运行我的代码,我也不想暴露太多的功能,因为第三方有可能访问通知设计器,而且我不希望任何人在通知中插入任何危险的代码。

因此,我编写了一个简单的表达式解析器/编译器/解释器,它提供了我希望公开的功能,并且不再提供更多功能,即属性读取、字符串连接、基本算法和日期/时间操作。对表达式进行一致性分析,检查类型并生成伪汇编程序代码,这些代码可以序列化并存储为字节序列,以便稍后在一组特定的对象实例上重新创建和执行,以获得最终的表达式结果。

解析/编译和执行发生在不同的上下文、不同的时间、不同的会话,甚至可能在不同的机器上,因此我需要能够从头开始重新创建调用链,将其作为通过基本类型对象的完全限定名获得的一系列PropertyInfo对象。

到目前为止,我只在分析调用链时才检查BindingFlags.Public | BindingFlags.Instance属性,但我看到了今后如何将实现扩展到包括静态属性之类的内容。因此,我不愿意假设任何特定的绑定标志集,我也不想浪费时间在表达式执行期间发现它,因为我在编译时知道它的值;我宁愿将它存储在序列化程序中,以便在重构调用链时将它直接传递给Type.GetProperty()

但是,我序列化已编译表达式的代码肯定不在我检查用户输入的某个文本片段是否是当前调用链中的有效属性的代码的本地作用域中,因此,当我需要值时,我早就忘记了在分析期间传递给Type.GetProperties()函数的参数。这就是我如何使用包含我想要存储的值的RuntimePropertyInfo,但是无法到达它,因为.NET编译器认为它是它的基类PropertyInfo的一个实例,它不包含BindingFlags属性。非常令人沮丧。

如果我必须将所使用的参数存储在其他地方,以便在程序序列化期间检索它们,那么我将这样做。但是,如果我能够简单地将对象转换为RuntimePropertyInfo的一个实例并读取它的BindingFlags属性,我的生活就会简单一些。

EN

回答 2

Stack Overflow用户

发布于 2018-04-18 20:01:47

代码语言:javascript
复制
var bindingFlags = 
ReflectionUtil.GetPrivatePropertyValue<BindingFlags>(propertyInfo, "BindingFlags");


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Xml.Serialization;
using HQ.Util.General.DynamicProperties;

namespace HQ.Util.General.Reflection
{
    public class ReflectionUtil
    {
        // ******************************************************************
        public static BindingFlags BindingFlagsAll = BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
        public static BindingFlags BindingFlagsPublic = BindingFlags.Public | BindingFlags.Instance;
        public static BindingFlags BindingFlagsAllButNotStatic = BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic;

        // ******************************************************************
        /// <summary>
        /// Will also set public property. Will set value in instance of any base class in hierarchy.
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="propertyName"></param>
        /// <param name="value"></param>
        public static void SetPrivatePropertyValue(object obj, string propertyName, object value)
        {
            PropertyInfo pi = GetPropertyInfoRecursive(obj.GetType(), propertyName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
            if (pi == null)
            {
                throw new ArgumentOutOfRangeException(propertyName, string.Format("Property {0} was not found in Type {1}", propertyName, obj.GetType().FullName));
            }
            pi.SetValue(obj, value);
        }

        // ******************************************************************
        /// <summary>
        /// Will also get public property. Will get value in instance of any base class in hierarchy.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        public static T GetPrivatePropertyValue<T>(object obj, string propertyName)
        {
            PropertyInfo pi = GetPropertyInfoRecursive(obj.GetType(), propertyName);
            if (pi == null)
            {
                throw new ArgumentOutOfRangeException(propertyName, string.Format("Property {0} was not found in Type {1}", propertyName, obj.GetType().FullName));
            }

            return (T)pi.GetValue(obj);
        }

        // ******************************************************************
        /// <summary>
        /// This is mainly used to look for private properties recursively because "FlattenHierarchy" is only applied on static members. 
        /// And also because private property could only be gotten for declared class type, not hierarchy.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="propertyName"></param>
        /// <param name="bindingFlags"></param>
        /// <returns></returns>
        public static PropertyInfo GetPropertyInfoRecursive(Type type, string propertyName, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
        {
            PropertyInfo pi = type.GetProperty(propertyName, bindingFlags);
            if (pi == null && type.BaseType != null)
            {
                pi = GetPropertyInfoRecursive(type.BaseType, propertyName, bindingFlags);
            }

            return pi;
        }
票数 0
EN

Stack Overflow用户

发布于 2022-10-01 11:57:38

像这样的黑客怎么样:

代码语言:javascript
复制
PropertyInfo propinfo;

bool isinstance  = Type.GetProperties(BindingFlags.Instance).Contains(propinfo);
bool ispublic  = Type.GetProperties(BindingFlags.Public).Contains(propinfo);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40545694

复制
相关文章

相似问题

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