2009-04-29 2 views
15

я могу спросить, это неправильно, но может/как вы можете найти поля на класс в себе ... например ...C# Отражение: Обнаружение атрибутов на поле членами

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

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

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

ответ

12

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

В методе 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"); 
      } 
     } 
    } 
+0

Спасибо. Это казалось «возможным», но опять же я подумал, что этого недостаточно, что он не может работать. – Hugoware

+2

Нет, метод Render отлично подходит для доступа к typeof (HtmlForm) вместо obj.GetType(), тогда вам больше не нужно obj. Конечно, если сам HtmlForm был закрыт, вам может потребоваться найти его через Assembly.GetExecutingAssembly(). GetTypes(). Где (t =>! T.IsGeneric &&! T.IsNested && t.FullName == "MyNamespace. HtmlForm ") или что-то в этом роде. – Timwi

5

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

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

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

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

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

+0

Спасибо за ответ - Сейчас это скорее эксперимент, чем все остальное. Я задавался вопросом, возможно ли это, поскольку это был причудливый способ попытаться получить эту информацию. – Hugoware

10

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

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

} 

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

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

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

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

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

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