Как передать PropertyInfo свойства как параметр в атрибуте? - PullRequest
0 голосов
/ 17 июля 2009

Допустим, у меня есть два класса:

class A
{
   [SortOrder(3)]
   public string Name { get; set; }
}

class B : A
{
   [SortBefore(*****)]
   public string Age { get; set; }
}

Обратите внимание на звезды в атрибуте свойства во втором классе. Можно ли как-то (используя выражения, я думаю) можно указать A.Name в атрибуте SortBefore? Обратите внимание, что я не за значением Name в экземпляре A, а через PropertyInfo для свойства Name в A, так что я при работе с PropertyInfo для Age в B могу извлечь значение SortOrder из его суперкласса.

Ответы [ 3 ]

3 голосов
/ 17 июля 2009

Боюсь, вы не можете. возможно возможно в IL - я не уверен - но вы не можете сделать это в C #.

Самое близкое, к чему вы могли бы прийти:

[SortBefore (typeof (A), «Имя»)]

и получить атрибут для поиска свойства во время выполнения. И да, это очень хрупко - если вы сделаете это, я бы добавил модульный тест, который находит все атрибуты в сборке и проверяет, все ли они действительны.

1 голос
/ 17 июля 2009

Даже оператор C # typeof реализован компилятором как ldtoken с последующим вызовом Type.GetTypeFromHandle(). PropertyInfo является особенно интересным случаем, потому что инструкция ldtoken IL не может принимать токен метаданных свойства в качестве аргумента и отсутствует тип RuntimePropertyHandle. Однако методы получения и / или установки могут быть получены в IL через (это не является действительным IL, но показывает инструкции). К сожалению, в C # нет прямого способа создать этот код с уровнем безопасности типов, который обеспечивает оператор typeof().

ldtoken <method>
call MethodBase.GetMethodFromHandle

Ответ на этот предыдущий вопрос показывает, как получить PropertyInfo из MethodInfo.

Ответ Джона верен в отношении решения, которое вам, вероятно, придется использовать.

0 голосов
/ 04 марта 2013

Просто чтобы добавить контекст того, что сказал Джон Скит: даже в IL это невозможно. Допустим, для ударов вы смогли получить MetadataToken для свойства, написав свой собственный компилятор и вставив маркер метаданных свойства в атрибут. Во время выполнения вы не сможете попросить модуль, из которого получено свойство, разрешить токен метаданных; Вы получите это сообщение:

Этот API не поддерживает токены PropertyInfo.

Способ проверить это - получить PropertyInfo любого свойства и запросить у модуля, который определяет тип, содержащий свойство, значение ResolveMember, которое принимает значение int токена метаданных, и передать его PropertyInfo.MetadataToken:

Console.WriteLine(propInfo.DeclaringType.Module.ResolveMember(propInfo.MetadataToken));

API не был разработан для этой цели, сами свойства - это просто метаданные, которые используются вместе с вашей программой, чтобы помочь связать методы с общим контекстом для использования с компиляторами и IDE. Как только компилятор берет ваш код и делает свое волшебство, свойство никогда не появляется ни разу в IL.

Если бы вы могли вставить MetadataToken свойства в атрибут, лучшее, что вы могли бы сделать, это также вставить MetadataToken типа в атрибут и заставить его извлечь объект PropertyInfo с помощью итерации Свойства типа, и тот с совпадающим MetadataToken будет вашей целью.

Крайне важно понимать, что MetadataToken уникальны только в пределах модуля, в котором они существуют. Я бы сказал, сборка, но несколько сборок модулей убивают эту идею.

Я знаю об этом только из написания парсера метаданных ECMA-335.

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