使用反射(或其他方式)获取成员对象

发布于 2024-10-19 04:38:17 字数 474 浏览 2 评论 0原文

我希望能够通过名称访问属性或类的成员。如果它是一个属性,我很好:

  PropertyInfo prop = object.GetType().GetProperty(propertyName);
  object propValue = prop.GetValue(object, null);

如果它是一个成员/字段,事情似乎有点棘手。在研究了 GetMember 并尝试了一堆不同的东西之后,我不知道如何以与从 GetProperty 返回对象相同的方式获取对象的引用,如果这是一种财产。

另一个问题是,这是实现这一目标的正确方法吗?在阅读有关反射的内容时,似乎有很多开销。这是否只是与不使用反射相比,或者它是否足够重要,以至于我应该三思而行开发一些将经常这样做的东西,以及我有什么替代方案(如果有的话)来获取对 a 成员的引用仅按名称分类?

感谢您的任何见解。如果有什么区别的话,我的目标是能够序列化任意命名的属性或类的成员。

I want to be able to access a property or member of a class by name. I'm fine if it's a property:

  PropertyInfo prop = object.GetType().GetProperty(propertyName);
  object propValue = prop.GetValue(object, null);

Things seem a little trickier if it is a member/field. AFter studying GetMember and trying a bunch of different stuff I can't figure out how to just get a reference to the object the same way it would be returned from GetProperty, if it was a property.

The other question is, is this the right way to accomplish this? In reading about reflection, it seems to have a lot of overhead. Is this just in comparison to not using reflection, or is it significant enough that I should think twice about developing something that will be doing this a lot, and what alternatives do I have, if any, to obtain a reference to a member of a class by name only?

Thanks for any insight. If it makes any difference, my goal is to be able to serialize an arbitrary named property or member of a class.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

卖梦商人 2024-10-26 04:38:17

您可以使用 GetField 而不是 GetProperty 如果你想要检索一个字段。

FieldInfo field = object.GetType().GetField(fieldName);
object fieldValue = field.GetValue(Context.Parent);

或者它是否足够重要,以至于我应该在开发一些经常这样做的东西时三思而后行,以及我有什么替代方案(如果有的话)来仅通过名称获取对类成员的引用?

它肯定很昂贵,但我会对其进行分析以确定您是否会遇到性能问题。

另一个主要选项是自己构建某种形式的字典,将“名称”映射到值。这可以是映射到值的直接字典,也可以是映射到检索值的委托的字典。这样做的优点是,您可以使其以相同的方式用于属性或字段,但每个类都需要创建映射。 (然而,这可以通过构建时的反射来完成。)

如果有什么区别的话,我的目标是能够序列化任意命名的属性或类的成员。

我建议查看内置的序列化支持< /a> 在推出您自己的版本之前...

You can use GetField instead of GetProperty if you want to retrieve a field.

FieldInfo field = object.GetType().GetField(fieldName);
object fieldValue = field.GetValue(Context.Parent);

or is it significant enough that I should think twice about developing something that will be doing this a lot, and what alternatives do I have, if any, to obtain a reference to a member of a class by name only?

It is definitely expensive, but I'd profile it to determine if you will have a performance issue.

The other main option(s) is to build some form of dictionary yourself that maps "names" to values. This can be a direct dictionary mapping to the value, or a dictionary that maps to a delegate which retrieves the value. This does have the advantage in that you can make it work the same way for properties or fields, but each class needs to create the mapping. (This can, however, potentially be done via reflection at construction time.)

If it makes any difference, my goal is to be able to serialize an arbitrary named property or member of a class.

I would recommend reviewing the built-in Serialization Support prior to rolling your own version...

你与清晨阳光 2024-10-26 04:38:17

如果您使用 C# 4.0(与 .NET Framework 4.0 和 Visual Studio 2010 一起发布),则新的 dynamic 关键字将简化代码中的内容:

dynamic myValue = anyObject;
string name = myValue.myField; // Resolved at runtime, not compile-time
bool result = myValue.myBooleanMethod(1, 2, 3); // Ditto

等等。我的理解是,这会做更多事情- 或者说,在幕后使用反射和测试是否存在兼容的 PropertyInfo/MethodInfo/etc 是一样的。然后调用它们,因此性能仍然是一个问题,但它的可读性肯定要高得多。

If you're using C# 4.0 (released alongside the .NET Framework 4.0 and Visual Studio 2010), there's the new dynamic keyword that will simplify things in your code:

dynamic myValue = anyObject;
string name = myValue.myField; // Resolved at runtime, not compile-time
bool result = myValue.myBooleanMethod(1, 2, 3); // Ditto

etc. My understanding is that this does more-or-less the same thing under the hood as using reflection and testing for the existence of compatible PropertyInfo/MethodInfo/etc. and then invoking them, so performance is still a concern, but it's certainly a lot more readable.

唔猫 2024-10-26 04:38:17

我对缓存的想法,欢迎评论。

    public static ConcurrentDictionary<Tuple<Type, string>, 
        Func<object, object[], object>> ReflectionCache
    {
        get
        {
            if (_ReflectionCache==null) {
                _ReflectionCache = new ConcurrentDictionary<Tuple<Type, string>,
                  Func<object, object[], object>>();
            }
            return _ReflectionCache;
        }
    } private static ConcurrentDictionary<Tuple<Type, string>, 
         Func<object, object[], object>> _ReflectionCache = null;

    public static object GetCachedProperty(object obj, string name)
    {
        Func<object,object[],object> del;
        if (!ReflectionCache.TryGetValue(Tuple.Create<Type,string>(obj.GetType(),
          name), out del)) {
            MemberInfo memberInfo = 
               (MemberInfo)obj.GetType().GetMember(name).GetValue(0);
            PropertyInfo prop = null;
            FieldInfo fld = null;

            switch(memberInfo.MemberType) {
            case MemberTypes.Field:
                fld = obj.GetType().GetField(name);
                break;
            case MemberTypes.Property:
                prop = obj.GetType().GetProperty(name);
                break;
            }

            if (prop == null && fld == null)
            {
                throw new Exception("No property or field named '" + name 
                 + "' could be found in the context parent.");
            }
            if (prop!=null) {
                prop= obj.GetType().GetProperty(name);
                del = prop.GetValue;
            } else {
                fld = obj.GetType().GetField(name);
                del = delegate(object cls,object[] index) {
                    return fld.GetValue(cls);
                };
            }

            ReflectionCache[Tuple.Create<Type,string>(obj.GetType(),name)]=del;
        }
        return(del(obj,null));
    }

What I came up with for caching, comments welcome.

    public static ConcurrentDictionary<Tuple<Type, string>, 
        Func<object, object[], object>> ReflectionCache
    {
        get
        {
            if (_ReflectionCache==null) {
                _ReflectionCache = new ConcurrentDictionary<Tuple<Type, string>,
                  Func<object, object[], object>>();
            }
            return _ReflectionCache;
        }
    } private static ConcurrentDictionary<Tuple<Type, string>, 
         Func<object, object[], object>> _ReflectionCache = null;

    public static object GetCachedProperty(object obj, string name)
    {
        Func<object,object[],object> del;
        if (!ReflectionCache.TryGetValue(Tuple.Create<Type,string>(obj.GetType(),
          name), out del)) {
            MemberInfo memberInfo = 
               (MemberInfo)obj.GetType().GetMember(name).GetValue(0);
            PropertyInfo prop = null;
            FieldInfo fld = null;

            switch(memberInfo.MemberType) {
            case MemberTypes.Field:
                fld = obj.GetType().GetField(name);
                break;
            case MemberTypes.Property:
                prop = obj.GetType().GetProperty(name);
                break;
            }

            if (prop == null && fld == null)
            {
                throw new Exception("No property or field named '" + name 
                 + "' could be found in the context parent.");
            }
            if (prop!=null) {
                prop= obj.GetType().GetProperty(name);
                del = prop.GetValue;
            } else {
                fld = obj.GetType().GetField(name);
                del = delegate(object cls,object[] index) {
                    return fld.GetValue(cls);
                };
            }

            ReflectionCache[Tuple.Create<Type,string>(obj.GetType(),name)]=del;
        }
        return(del(obj,null));
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文