Кисточка у художника может быть разной, а можно и совсем без кисточки. В С++ типы исчезали после трансляции, а вот в C# они не исчезают и могут быть использованы на этапе выполнения. С# — это располневшая на мелкософтах Дельфи и основная причина юзанья атрибутов с типами — PropertyGrid, бывший TValueListEditor. Ну а потом можно придти к не очевидному выводу, что атрибуты с типами — просто и удобно.
Раньше методы, поля и свойства класса были чисто феней промеж кодерами, можно было сказать метод, а можно — функция, можно — поле, а можно — просто переменная. Но коль скоро есть тип в памяти, то к нему можно обращаться, а обращаясь нужно использовать точные термины. От любого объекта можно получить его тип, а от типа можно получить имена полей, свойств и методов, а по именам можно получить значение поля — т.е. уже другой объект, или вызвать метод со всеми параметрами и возвращаемым значением.
class X { class A { public int f1; public int p1 { get; set; } public int m1(string s, int i) { return (0); } } X() { A a = new A(); Type t = a.GetType(); FieldInfo fi = t.GetField("f1"); object of = fi.GetValue(a); PropertyInfo pi = t.GetProperty("p1"); MethodInfo mpi = pi.GetGetMethod(); object ompi = mpi.Invoke(a, null); MethodInfo mi = t.GetMethod("m1"); object om = mi.Invoke(a, new object[] { "param1", 2 }); } }
Таким образом, мы получили альтернативный запутаистичный способ программирования, когда мы можем писать не сами переменные, а их строковые имена. Строковые имена можно менять.
Каждый объект имеет две ипостаси: с одной стороны он есть поле какого то типа, а с другой стороны он сам имеет свой тип, в котором могут быть разные поля. Типы на этапе выполнения изменить нельзя, кроме как обратиться по адресу в памяти хакерским методом.
У каждого типа есть список атрибутов, этот список может быть пуст, а может быть и полон. Вот тут и начинается самое интересное. Оказывается у каждого объекта свой собственный уникальный тип. Иначе говоря, две переменные типа int имеют два разных типа. Эти типы могут быть одинаковы, а могут быть и различны, и различаться они будут списком атрибутов. Понятно, что exe-шник не переполняется повторяющимися типами, реализация идет через ссылки, но в дырявом представлении уровня кодера это именно так.
class X { class ATTR1 : Attribute { public ATTR1() { } } class ATTR2 : Attribute { public ATTR2() { } } class A { [ATTR1] public int i1; [ATTR2] public int i2; } X() { object[] ai1 = a.i1.GetType().GetCustomAttributes(false); object[] ai2 = a.i2.GetType().GetCustomAttributes(false); } }
У объектов никаких атрибутов нет, атрибуты только у типов. От каждого объекта мы можем получить его тип, а в типе найти атрибуты. Но коль скоро тип у каждого объекта уникальный, то можно сказать, что у объекта есть атрибуты. Однако можно так же сказать, что объект описан в некотором типе, а в этом типе к этому объекту так же приписаны атрибуты. Таким образом, у объекта есть два списка атрибутов – список по его собственному типу, и список по типу, в котором этот объект описан.
class X { class ATTR1 : Attribute { public ATTR1() { } } class ATTR2 : Attribute { public ATTR2() { } } [ATTR1] class A { } [ATTR2] A a; X() { a = new A(); object[] inner = a.GetType().GetCustomAttributes(false); object[] outer = this.GetType().GetField("a").GetCustomAttributes(false); } }
Атрибуты есть не только у полей, но и у методов, и у свойств. Чтобы использовать атрибуты их сперва нужно найти у объекта. Когда мы ищем атрибуты у объекта, то мы должны выбрать соответствующий список, а когда прописываем атрибуты – соответственно писать в тот тип, который следует. Зачастую кодер на всякий случай проверяет атрибуты и там и там, а при противоречии атрибутов отдает приоритет атрибуту поля перед атрибутом типа.
Первобытные кодеры полагали, что главное это прогу закодить. Потом предки пришли к тому, что главное это данные заструктурить. В наш просвещенный век универсальные проги бороздят просторы структурированного океана данных, наводя там новый порядок. Одна из таки программ – PropertyGrid, которая показывает на экране дерево данных с возможностью их изменить. Как найдет public property – так сразу и покажет. А если property такое нестандартное, что его ни посмотреть, ни отредактировать, то PropertyGrid поищет атрибутик с описанием класса, которым можно посмотреть и поправить property. А если не найдет – то и показывать не станет. А че, СУБД давно хранят типы своих данных и живут припеваючи, почему бы и проге их не хранить – памяти на компах теперь складывать некуда, а на скоростях можно и неуправляемый кусочек закодить.
Известные глюки.
Усё работает внутри c#, но стоит выставить в OLE (COM, ActiveX), как сразу теряются некоторые атрибуты, скорее всего при переходе от одной c# dll к другой. Например когда сама полянка (field) описана в одной dll, а ее тип с атрибутом — в другой, при чем атрибут то не пропадет, пропадут его полянки — он же тоже класс в свою очередь. Трудно определить где конкретно глюк. Вероятнее всего CCW вальтует. CCW — это такое волшебное слово, означающее обёртку со сборщиком мусора для неуправляемого вызова. Шарповцы полагают, что кодеры будут писать на шарпе и изредка подтягивать свои старые наработки на плюсах, а сами кодеры полагают, что они будут сопровождать своих монстров допиливая к ним кусочки на шарпе.
ссылка на оригинал статьи http://habrahabr.ru/post/267515/
Добавить комментарий