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

时间:2011-02-25 20:21:44

标签: c# reflection

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

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

如果是会员/领域,事情似乎有点棘手。在研究GetMember并尝试了一堆不同的东西之后,我无法弄清楚如何以GetProperty返回的方式获取对象的引用,如果它是属性的话

另一个问题是,这是实现这一目标的正确方法吗?在阅读反思时,它似乎有很多开销。这只是与不使用反射相比,还是足够重要,我应该三思而后行,开发一些会做很多事情的东西,以及我有什么替代品,如果有的话,可以获得对一个成员的引用只按姓名分类?

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

3 个答案:

答案 0 :(得分:4)

如果您想要检索字段,可以使用GetField代替GetProperty

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

还是足够重要,我应该三思而后行,开发一些会做很多事情的东西,以及我有什么选择,如果有的话,只能通过名字获得对一个类成员的引用?

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

另一个主要选项是自己构建某种形式的字典,映射"名称"价值观。这可以是映射到值的直接字典,也可以是映射到检索值的委托的字典。这样做的好处在于,您可以使它以相同的方式用于属性或字段,但每个类都需要创建映射。 (但是,这可以通过施工时的反射来完成。)

  

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

我建议在推出自己的版本之前检查内置的Serialization Support ...

答案 1 :(得分:0)

如果你正在使用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 /等相比,这或多或少是相同的。然后调用它们,因此性能仍然是一个问题,但它肯定更具可读性。

答案 2 :(得分:0)

我想出了什么用于缓存,欢迎评论。

    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));
    }