Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Delphi XE4, лёгкий баг в аттрибутах / 4 сообщений из 4, страница 1 из 1
03.01.2018, 19:33
    #39579087
Dimonka
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Delphi XE4, лёгкий баг в аттрибутах
Сразу зафигачу безразмерный листинг для тех кто такого не страшится.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  rtti;

type
  // TSomeType = (stA, stB, stC);
  TSomeType = (stA, stB, stC, stD, stE, stF, stG, stH, stI, stJ, stK, stL, stM,
    stN, stO, stP, stQ, stR, stT, stU, stV, stW, stX, stY, stZ, st0, st1, st2,
    st3, st4, st5, st6, st7, st8, st9);
  TSomeTypeSet = set of TSomeType;
type
  SomeAttribute = class(TCustomAttribute)
  private
    FElements: TSomeTypeSet;
  public
    constructor Create({const }AttrElements: TSomeTypeSet);
    property Elements: TSomeTypeSet read FElements;
  end;

  [SomeAttribute([stA, stC])]
  TClassWithAttribute = class
  end;

function GetChildrenFor(aClass: TClass): TSomeTypeSet;
var
  rttiContext: TRttiContext;
  rttiType: TRttiType;
  attribute: TCustomAttribute;
begin
  rttiContext := TRttiContext.Create;
  try
    rttiType := rttiContext.GetType(aClass);
    for attribute in rttiType.GetAttributes do  // <- падает здесь
      if attribute is SomeAttribute then
        Exit(SomeAttribute(attribute).Elements);
    Result := [];
  finally
    rttiContext.Free;
  end; // try to recover and return the DisplayLabel
end;

{ SomeAttribute }

constructor SomeAttribute.Create({const }AttrElements: TSomeTypeSet);
begin
  FElements := AttrElements;
end;

var
  Elements: TSomeTypeSet;
  El: TSomeType;
begin
  try
    Elements := GetChildrenFor(TClassWithAttribute);
    for El in Elements do
      Writeln(format('Element: %d', [integer(El)]));
    readln;
  except
    on E: Exception do
    begin
      Writeln(E.ClassName, ': ', E.Message);
      readln;
    end;
  end;
end.


Смысл бага в том, что в атрибут компилируется разный тип данных в зависимости от количества елементов в перечисляемом типе.
Если в типе TSomeType оставить несколько элементов - приведённая программа работает, иначе падает, потому что вместо сета в аттрибут передаётся массив из 2-х элементов и при создании атрибута инвокер конструктора падает с ошибкой Invalid class typecast.

Не знаю, есть ли здесь что обсуждать и решён ли баг в более новых версиях, но оставлю это здесь для информации.
...
Рейтинг: 0 / 0
03.01.2018, 20:02
    #39579102
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Delphi XE4, лёгкий баг в аттрибутах
Dimonka,

Если я не ошибаюсь, баг связан с некорректным определением размера множества. Пофикшен, вроде, в берлине только.
...
Рейтинг: 0 / 0
03.01.2018, 20:09
    #39579103
Dimonka
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Delphi XE4, лёгкий баг в аттрибутах
Попробовал передать список элементов как array of const, ошибка:
E2150 Bad argument type in variable type array constructor
Похоже Дельфи не очень любит сеты с количеством элементов > 32
...
Рейтинг: 0 / 0
03.01.2018, 20:26
    #39579107
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Delphi XE4, лёгкий баг в аттрибутах
DimonkaПохоже Дельфи не очень любит сеты с количеством элементов > 32
Да, именно для таких сетов в RTTI размер хранится с минусом.
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Delphi XE4, лёгкий баг в аттрибутах / 4 сообщений из 4, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]