Получить объект члена, используя отражение (или каким-либо другим способом) - PullRequest
1 голос
/ 25 февраля 2011

Я хочу иметь доступ к свойству или члену класса по имени. Я в порядке, если это свойство:

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

Вещи кажутся немного хитрее, если это элемент / поле. После изучения GetMember и пробуя кучу разных вещей, я не могу понять, как просто получить ссылку на объект так же, как он будет возвращен из GetProperty, если бы это было свойство.

Другой вопрос, это правильный путь для достижения этой цели? В чтении об отражении, кажется, много накладных расходов. Это просто по сравнению с неиспользованием рефлексии, или это достаточно важно, чтобы я дважды подумал о разработке чего-то, что будет делать это много, и какие у меня есть альтернативы, если есть, чтобы получить ссылку на члена класс только по имени?

Спасибо за понимание. Если это имеет какое-то значение, моя цель - иметь возможность сериализовать произвольное именованное свойство или член класса.

Ответы [ 3 ]

4 голосов
/ 25 февраля 2011

Вы можете использовать GetField вместо GetProperty, если хотите извлечь поле.

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

или это достаточно важно, чтобы я дважды подумал о разработкечто-то, что будет делать это много, и какие у меня есть альтернативы, если таковые имеются, чтобы получить ссылку на члена класса только по имени?

Это определенно дорого, но я 'd профилируйте его, чтобы определить, не возникнет ли у вас проблемы с производительностью.

Другой основной вариант (ы) - это самостоятельно создать некую форму словаря, которая сопоставляет «имена» со значениями.Это может быть прямое сопоставление словаря со значением или словарь, который сопоставляется с делегатом, который извлекает значение.Это имеет то преимущество, что вы можете заставить его работать одинаково для свойств или полей, но каждый класс должен создать отображение.(Однако это потенциально может быть сделано с помощью отражения во время построения.)

Если это имеет какое-то значение, моя цель - иметь возможность сериализации произвольного именованного свойства или члена класса.

Я бы порекомендовал ознакомиться со встроенной поддержкой сериализации перед выпуском собственной версии ...

0 голосов
/ 26 февраля 2011

Что я придумал для кеширования, комментарии приветствуются.

    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));
    }
0 голосов
/ 25 февраля 2011

Если вы используете 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 / и т. Д.и затем вызывать их, так что производительность по-прежнему является проблемой, но, безусловно, гораздо более читабельной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...