Отражение в C #: поиск атрибутов в поле участника - PullRequest
16 голосов
/ 29 апреля 2009

Я, возможно, спрашиваю это неправильно, но может / как вы можете найти поля в классе внутри себя ... например ...

public class HtmlPart {
  public void Render() {
    //this.GetType().GetCustomAttributes(typeof(OptionalAttribute), false);
  }
}

public class HtmlForm {
  private HtmlPart _FirstPart = new HtmlPart();      
  [Optional] //<-- how do I find that?
  private HtmlPart _SecondPart = new HtmlPart();
}

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

Кроме того, ради вопроса - Мне просто любопытно, можно ли было найти информацию об атрибутах без знания / доступа к родительскому классу!

Ответы [ 3 ]

13 голосов
/ 29 апреля 2009

Если я правильно понимаю ваш вопрос, я думаю, что вы пытаетесь сделать, это невозможно ...

В методе Render вы хотите получить возможный атрибут, примененный к объекту. Атрибут принадлежит полю _SecondPart, принадлежащему классу HtmlForm.

Чтобы это работало, вам нужно передать вызывающий объект методу Render:

    public class HtmlPart {
        public void Render(object obj) {
            FieldInfo[] infos = obj.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);

            foreach (var fi in infos)
            {
                if (fi.GetValue(obj) == this && fi.IsDefined(typeof(OptionalAttribute), true))
                    Console.WriteLine("Optional is Defined");
            }
        }
    }
10 голосов
/ 29 апреля 2009

Вот пример для одного объекта, как найти, имеют ли какие-либо открытые или закрытые поля этого объекта определенное свойство:

var type = typeof(MyObject);
foreach (var field in type.GetFields(BindingFlags.Public |
             BindingFlags.NonPublic | BindingFlags.Instance))
{
    if (field.IsDefined(typeof(ObsoleteAttribute), true))
    {
        Console.WriteLine(field.Name);
    }

}

Для второй части вашего вопроса вы можете проверить, является ли атрибут защищенным в текущем методе, используя:

MethodInfo.GetCurrentMethod().IsDefined(typeof(ObsoleteAttribute));

Редактировать

Чтобы ответить на ваши изменения, да, это возможно, не зная фактического типа. Следующая функция принимает тип Parameter и возвращает все поля, которые имеют данный атрибут. Кто-то где-то собирается узнать тип, который вы хотите найти, или у вас будет экземпляр типа, который вы хотите найти.

Без этого вам пришлось бы делать, как сказал Джон Скит, что перечислять все объекты в сборке.

   public List<FieldInfo> FindFields(Type type, Type attribute)
    {
        var fields = new List<FieldInfo>();
        foreach (var field in type.GetFields(BindingFlags.Public |
                           BindingFlags.NonPublic |
                           BindingFlags.Instance))
        {
            if (field.IsDefined(attribute, true))
            {
                fields.Add(field);
            }

        }
        return fields;
    }
5 голосов
/ 29 апреля 2009

Вы можете найти поля внутри класса, используя Type.GetFields, и вы можете найти атрибуты, примененные к полю, используя MemberInfo.GetCustomAttributes или IsDefined - но если вам нужно найти все поля определенного типа, вы придется:

  • Перебор всех сборок, которые вы хотите найти
  • Перебирать все типы в каждой сборке
  • Перебирать все поля внутри каждого типа
  • Проверка наличия / отсутствия атрибута для каждого поля

Теперь, если вы действительно пытаетесь выяснить, «является ли конкретный атрибут, примененный к полю, значением которого является ссылка на« этот »объект», то это еще сложнее - потому что вы должны знать все о каждом объекте в системе. Следует также иметь в виду, что могут быть два поля, оба с одинаковым значением, т. Е. Ссылающиеся на один и тот же объект. Будет ли объект считаться «необязательным» в этом случае или нет?

По сути, если объект должен иметь свойство (например, необязательное или нет), то это должно быть свойство самого объекта, а не поле, содержащее свойство.

Возможно, я неверно истолковываю то, что вы пытаетесь сделать, но я подозреваю это либо неосуществимо, либо, по крайней мере, не очень хорошая идея. Не могли бы вы объяснить более широкую картину здесь? Чего вы действительно хотите достичь с помощью этого атрибута?

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