type
TTypeOfData = (todABC, todDEF, todGHI);
TMySerializableClass = class
private
FType: TTypeOfData;
public
property &Type: TTypeOfData read FType write FType;
class function TypeOfDataAsString(&Type: TTypeOfData): String;
end;
implementation
class function TMySerializableClass.TypeOfDataAsString(&Type: TTypeOfData): String;
const
TYPE_STRING: array[TypeOfDataAsString] of String = ('ABC', 'DEF', 'GHI);
begin
Result := TYPE_STRING[&Type];
end;
procedure Serialize(const V: TValue);
var
N: String;
T: TRttiType;
F: TRttiField;
M: TRttiMethod;
R: TValue;
begin
case V.TypeInfo^.Kind of
tkEnumeration:
begin
T := Ctx.GetType(TypeInfo(TMySerializableClass));
N := V.TypeInfo.Name + 'AsString';
if N[1] = 'T' then
Delete(N, 1, 1);
M := T.GetMethod(N);
if (M <> nil) and M.IsClassMethod and (M.MethodKind = mkClassFunction) and (M.ReturnType.TypeKind = tkUString) then
begin
R := M.Invoke(TTicket, [V]);
// serialize R.AsString
end;
end;
...
end;
7条答案
按热度按时间zy1mlcev1#
虽然巴里清楚地回答了你关于枚举元素属性的问题,但我会尝试另一个建议。从你的例子中,你用'tod'作为每个枚举元素的前缀,这是 Delphi 中的传统做法,因为枚举元素在作用域中是全局的(即,如果你在作用域中除了todABC枚举元素之外还有一个标识符todABC,你可能会得到一些奇怪的行为)。
从D2007开始,我们引入了“scoped enums”的概念,当启用时,需要使用enum本身的标识符来限定enum元素。例如:
将要求您将ABC元素引用为TTypeOfData. ABC。这允许您使用无前缀的枚举元素标识符,并且不会冒发生冲突的风险,因为元素的“作用域”是枚举。启用{$SCOPEDENUMS}时声明的任何枚举都将以这种方式运行。
考虑到这一点,您现在可以安全地使用RTTI以您希望的格式获取实际的枚举元素名称。
jyztefdp2#
与枚举中的元素相关联的属性当前不存储在可执行文件的Win32 RTTI数据中。RTTI已经负责可执行文件大小的公平增加,因此必须在某处绘制一些行。 Delphi Win32中的属性支持类型,记录字段,字段,方法,它们的参数和类的属性。
由于与 Delphi for. NET的向后兼容性,属性声明不会导致错误。
bnl4lu3b3#
以下是 Delphi 2010中RTTI的一个很好的概述:http://robstechcorner.blogspot.com/2009/09/so-what-is-rtti-rtti-is-acronym-for-run.html
你可以使用TypInfo(GetEnumValue,GetEnumName)单元中的“OLD”RTTI函数来获取枚举值并返回序数。并剪掉小写字母,你会得到与上面相同的结果,但它不那么灵活。
wpcxdonn4#
好的,我想我找到了一个更好的解决方案。我声明了一个新的属性类型,例如:
现在我将属性添加到枚举中:
现在很容易通过序数访问属性:
z2acfund5#
对于那些对这个问题的实际解决方案感兴趣的人,我是这样解决的:
稍后,在序列化代码中,我使用RTTI查找一个通常名为AsString的类函数,并使用属性TValue调用它:
ryoqjall6#
我在const部分使用了字符串的数组:
tuwxkamq7#
我使用自定义属性。