Dimka, обрати внимание, что атрибут наследуемый - при определении класса атрибутов я указал явно Inherited = true (но этого можно и не делать, оно по умолчанию true).
Немного переписал пример до адекватного состояния.
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
public class MyAttrAttribute : Attribute
{
public string S { get; set; }
public MyAttrAttribute(string s)
{
S = s;
}
}
public class A
{
[MyAttr("abc")]
public virtual void Foo(int a)
{
}
}
public class B : A
{
public override void Foo(int a)
{
}
}
Type t = typeof(B);
MethodInfo mi = t.GetMethod("Foo");
MyAttrAttribute atr = (MyAttrAttribute)Attribute.GetCustomAttribute(mi, typeof(MyAttrAttribute), true);
if (atr != null)
{
Console.WriteLine(atr.S);
}
Наследуемый атрибут применяем к виртуальному методу Foo базового класса. Теперь мы, допустим, хотим узнать, помечен ли атрибутом переопределённый метод в классе B. Метод Attribute.GetCustomAttribute смотрит метаданные метода в классе B, не найдя там экземпляра нашего атрибута, просматривает базовые классы (для этого третьим параметром в GetCustomAttribute для наглядности передаём true, можно вызвать без этого параметра, по-умолчанию всё равно true). И на выходе программы будет - "abc" - всё работает.
С параметрами тоже работает. А с возвращаемым значением - нет. В любом случае по документации GetCustomAttribute не должен вызывать такое исключение. Явно баг.
Добавлено через 54 минуты и 59 секунд:Убери override-метод или добавь атрибут к override-методу, и всё взлетит.
Если убрать override - заработает. Тогда по иерархии классов не надо проходиться.
Если добавить атрибут к override-методу - ничего не изменится, я об оэтом писал уже. Хотя GetCustomAttribute возвращает ссылку только на один экземпляр атрибута, он проверяет, не применялся ли атрибут несколько раз (тогда бросает исключение). Поэтому, если мы вызываем GetCustomAttribute с параметром inherit = true для виртуальных методов, он вынужден пройтись по всем базовым классам.