С# Отражение: поиск атрибутов на поле члена
Возможно, я задаю это неправильно, но могу/как вы можете найти поля в классе внутри себя... например...
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();
}
Или, может быть, я просто делаю это неправильно... Как я могу вызвать метод, а затем проверить атрибуты, применяемые к себе?
Кроме того, ради вопроса - мне просто любопытно, можно ли находить информацию об атрибутах, не зная/получая доступ к родительскому классу!
Ответы
Ответ 1
Если я правильно понимаю ваш вопрос, я думаю, что то, что вы пытаетесь сделать, невозможно...
В методе 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");
}
}
}
Ответ 2
Здесь приведен пример одного объекта, как найти, имеют ли какие-либо общедоступные или частные поля на этом объекте определенное свойство:
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));
Edit
Чтобы ответить на ваше редактирование да, это возможно, не зная фактического типа. Следующая функция принимает параметр 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;
}
Ответ 3
Вы можете найти поля в классе с помощью Type.GetFields
, и вы можете найти атрибуты, применяемые к полю, используя MemberInfo.GetCustomAttributes
или IsDefined
- но если вам нужно найти все поля определенного типа, вы придется:
- Итерации по всем узлам, которые вы хотите искать
- Итерация по всем типам внутри каждой сборки
- Итерации по всем полям в каждом типе
- Проверить наличие/отсутствие атрибута для каждого поля
Теперь, если вы действительно пытаетесь выяснить, "это особый атрибут, применяемый к полю, значение которого является ссылкой на объект 'this'", то это еще сложнее - потому что вам нужно будет знать все о каждом объекте в системе. Вы также должны иметь в виду, что могут быть два поля с одинаковым значением, то есть ссылки на один и тот же объект. Будет ли объект считать "необязательным" в этом случае или нет?
В принципе, если объект должен иметь свойство (например, необязательное или нет), то это должно быть свойство самого объекта, а не поле, содержащее свойство.
Возможно, я неправильно интерпретирую то, что вы пытаетесь сделать, но я подозреваю, что это либо невозможно, либо, по крайней мере, не очень хорошая идея. Не могли бы вы объяснить здесь большую картину? Что вы действительно пытаетесь достичь с помощью этого атрибута?