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

C# 使用反射(或其他方式)获取成员对象,c#,reflection,C#,Reflection,我希望能够通过名称访问属性或类的成员。如果这是一处房产,我很好: PropertyInfo prop = object.GetType().GetProperty(propertyName); object propValue = prop.GetValue(object, null); 如果它是一个成员/字段,事情似乎有点棘手。在研究了GetMember并尝试了一系列不同的东西之后,我想不出如何像从GetProperty返回对象(如果它是一个属性)一样获取对该对象的引用 另一个问题是

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

  PropertyInfo prop = object.GetType().GetProperty(propertyName);
  object propValue = prop.GetValue(object, null);
如果它是一个成员/字段,事情似乎有点棘手。在研究了
GetMember
并尝试了一系列不同的东西之后,我想不出如何像从
GetProperty
返回对象(如果它是一个属性)一样获取对该对象的引用

另一个问题是,这是实现这一目标的正确方法吗?在阅读关于反思的文章时,它似乎有很多开销。这仅仅是相对于不使用反射而言的吗?或者它是否足够重要,以至于我应该在开发一些将大量使用反射的东西时三思而后行?如果有的话,我有什么替代方法来获得对一个类成员的名称引用

谢谢你的洞察力。如果有什么不同,我的目标是能够序列化任意命名的属性或类的成员。

如果要检索字段,可以使用而不是
GetProperty

FieldInfo field = object.GetType().GetField(fieldName);
object fieldValue = field.GetValue(Context.Parent);
或者,我应该三思而后行,开发一些能够大量实现这一点的东西,这是否足够重要?如果有的话,我有什么选择来获得对一个类成员的名称引用

这肯定是昂贵的,但我会分析它,以确定您是否会有性能问题

另一个主要选项是自己构建某种形式的字典,将“名称”映射到值。这可以是直接映射到值的字典,也可以是映射到检索值的委托的字典。这样做的好处在于,可以使它以相同的方式处理属性或字段,但每个类都需要创建映射。(但是,这可能通过在构建时进行反射来实现。)

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

我建议在滚动您自己的版本之前查看内置的…

如果要检索字段,可以使用而不是
GetProperty

FieldInfo field = object.GetType().GetField(fieldName);
object fieldValue = field.GetValue(Context.Parent);
或者,我应该三思而后行,开发一些能够大量实现这一点的东西,这是否足够重要?如果有的话,我有什么选择来获得对一个类成员的名称引用

这肯定是昂贵的,但我会分析它,以确定您是否会有性能问题

另一个主要选项是自己构建某种形式的字典,将“名称”映射到值。这可以是直接映射到值的字典,也可以是映射到检索值的委托的字典。这样做的好处在于,可以使它以相同的方式处理属性或字段,但每个类都需要创建映射。(但是,这可能通过在构建时进行反射来实现。)

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

我建议您在推出自己的版本之前先查看内置版本…

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

dynamic myValue = anyObject;
string name = myValue.myField; // Resolved at runtime, not compile-time
bool result = myValue.myBooleanMethod(1, 2, 3); // Ditto
我的理解是,这与使用反射和测试compatible
PropertyInfo
/
MethodInfo
/等的存在性差不多,然后调用它们,因此性能仍然是一个问题,但它肯定更具可读性。

如果您使用的是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

我的理解是,这与使用反射和测试兼容的
属性info
/
MethodInfo
/等的存在差不多,然后调用它们,所以性能仍然是一个问题,但它肯定更具可读性欢迎光临

    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));
    }
公共静态ConcurrentDictionary ReflectionCache
{
收到
{
if(_ReflectionCache==null){
_ReflectionCache=新的ConcurrentDictionary();
}
return\u ReflectionCache;
}
}私有静态ConcurrentDictionary _ReflectionCache=null;
公共静态对象GetCachedProperty(对象对象,字符串名称)
{
Func del;
如果(!ReflectionCache.TryGetValue)(Tuple.Create(obj.GetType()),
姓名),不包括姓名){
MemberInfo MemberInfo=
(MemberInfo)obj.GetType().GetMember(名称).GetValue(0);
PropertyInfo prop=null;
FieldInfo fld=null;
开关(memberInfo.MemberType){
案例成员类型。字段:
fld=obj.GetType().GetField(名称);
打破
案例成员类型。属性:
prop=obj.GetType().GetProperty(名称);
打破
}
if(prop==null&&fld==null)
{
抛出新异常(“没有名为“”的属性或字段+名称
+“'可以在父上下文中找到。”);
}
如果(prop!=null){
prop=obj.GetType().GetProperty(名称);
del=prop.GetValue;
}否则{
fld=obj.GetType().GetField(名称);
del=委托(对象cls,对象[]索引){
返回fld.GetValue(cls);
};
}
ReflectionCache[Tuple.Create(obj.GetType(),name)]=del;
}
返回(del(obj,null));
}

我为缓存提出的建议,欢迎评论

    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));
    }
公共静态ConcurrentDictionary ReflectionCache
{
收到
{
如果(_ReflectionCache==