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