Delphi属性真实世界的例子在哪里?

Ple*_*rds 12 delphi oop attributes rtti

我知道TMS Aurelius我们可以使用"new"2010属性功能在运行时将数据库表字段序列化为对象属性,例如,我不是这个深层面向对象架构的专家,所以我调查了TMS源代码并不能理解如何自己实现它,不是为了DB,而是为了XML.

所以我已经查找了所有Google的结果Delphi Attributes,所有人发布的都是声明示例,然后在显示他们的示例实际运行之前停止.

然后,我们如何在表单/执行代码中投射,声明,编码和使用那些juiced类的真实世界示例在哪里?

有没有人有一个例子在这里分享或知道一篇完整的好文章?

EDIT1:

答案应该有TForm一个TButton地方,点击后,执行一些使用创建的属性类的,不回答只显示属性和类的接口,因为有许多这样的例子声明我曾告诉过

pf1*_*957 10

我必须说我不太清楚你需要什么样的例子.恕我直言http://docwiki.embarcadero.com/RADStudio/XE4/en/Overview_of_Attributes是你应该需要的一切,也许你可以提供一些注释和/或方面编程的基本知识.

一个示例取决于特定SW使用属性的作者的方式/目的.你提到的ORM系统:这里的典型用法是注释表示在这样的框架的后端的数据库操作的更多信息neccessary DB实体类的成员.假设您有一个DB实体,其字段为COMPANY CHAR(32)NOT NULL,并且您希望在Delphi类中表示它:

TSomeDBEntity = class(...)
  FCDS: TClientDataset;
  ...
  constructor Create;
  ... 
  [TCharColumn('COMPANY', 32, false)]
  property CompanyName: string read GetCompanyName write SetCompanyName;
end;
Run Code Online (Sandbox Code Playgroud)

然后,您将使用构造函数定义属性TCharColumn

constructor TCharColumn.Create(const AFieldName:string; ALength:integer; ANullable:boolean);
begin
  inherited;
  FName := AFieldName;
  FLength := ALength;
  FNullable := ANullable;
end;
Run Code Online (Sandbox Code Playgroud)

这种注释的用法可能如下所示:

FCDS := TClientDataset.Create(nil);
RttiContext := TRttiContext.Create;
try
  RttiType := RttiContext.GetType(self.ClassType);
  Props := RttiType.GetProperties;
  for Prop in Props do
    begin
      Attrs := Prop.GetAttributes;
      case Prop.PropertyType.TypeKind of
        tkUString:
          begin
            for Attr in Attrs do
              if Attr is TCharColumn then
              begin
                ColAttr := TCharColumn(Attr);
                FCDS.FieldDefs.Add(ColAttr.FName, ftString, ColAttr.FLength, not ColAttr.FNullable);
              end;
          end;
        else
          //... ;
      end;
    end;
finally
  RttiContext.Free;
end;
Run Code Online (Sandbox Code Playgroud)

这个程序演示了如何在Delphi中基于注释在运行时定义数据集中的字段.由于缺少命名参数,我们的位置有限,因此使用参数列表并不灵活,例如在Java中(比较TMS Aurelius注释集http://www.tmssoftware.com/site/manuals/aurelius_manual.pdfhttp://www.techferry.com/articles/hibernate-jpa-annotations.html


小智 9

不确定问题是否要求使用属性使用的真实世界示例或如何使用属性将db表序列化为对象.下面的例子是一个人为的简单例子(但不仅仅是一个例子),展示了如何使用属性来记录对象属性的更改.

定义自定义属性

//By convention attributes are *not* prefixed with a `T` 
//and have the word `Attribute` in their name
LoggableAttribute = class(TCustomAttribute)
  private
    FDescription : String;
  public
    constructor Create(Description: String);
    property Description: String read FDescription;
  end;
Run Code Online (Sandbox Code Playgroud)

TProduct类的"hello world"使用该属性

TProduct = Class(TObject)
   private
    FPrice: Double;
    FDescription: String;
    ..
   public  
    [LoggableAttribute('Product Price')]
    property Price : Double read FPrice write SetPrice;
    [Loggable('Product Description')]   {the `Attribute` part is optional}
    property Description : String read FDescription write SetDescription;
    property IsDirty : Boolean read FIsDirty;
  End;
Run Code Online (Sandbox Code Playgroud)

任何具有"loggable属性"的类都可以传递给此方法,以迭代属性并记录它们.

procedure LogChanges(LoggableClass: TObject);
var
 c : TRttiContext;
 t : TRttiType;
 p : TRttiProperty;
 a : TCustomAttribute;
 Value : TValue;
begin
 c := TRttiContext.Create;    
 try
   t := c.GetType(LoggableClass.ClassType);
   for p in t.getProperties do
     for a in p.GetAttributes do
       if a is TLoggableProperty then begin
         Value := p.GetValue(LoggableClass);   
         // log to db.. 
         AddLogEntry(p.Name, TLoggableProperty(a).Description, Value.ToString);
       end;
 finally
   c.Free;
 end;
Run Code Online (Sandbox Code Playgroud)

结束;

使用示例:

var
 P : TProduct;
begin    
 P := TProduct.Create; 
 P.LoadPropertiesFromDB;
 ...
 ... User edits price ...    
 ... 
 P.Price := 499.99;
 ...
 ... Save product to DB 
 if P.IsDirty then  // save and log
   LogChanges(P);
Run Code Online (Sandbox Code Playgroud)


Ale*_*xSC 8

如果要声明自己的属性,可以这样做:

type
  TDisplayLabelAttribute = class(TCustomAttribute)
  private
    FText: string;
  public
    constructor Create(const aText: string);
    property Text: string read FText write FText;
  end;
Run Code Online (Sandbox Code Playgroud)

属性是常规类,其TCustomAttribute作为其祖先.你像往常一样实现它:

implementation

constructor TDisplayLabelAttribute.Create(const aText: string);
begin
  FText := aText;
end;
Run Code Online (Sandbox Code Playgroud)

现在声明并实现了属性,您可以使用它:

[DisplayLabel('My Class')]
TMyClass = class
end;
Run Code Online (Sandbox Code Playgroud)

所以现在你已经声明并实现了一个属性,并且你已经用它来为某个类添加一个显示标签.最后阶段是使用该属性,因为你有一个用它装饰的类.使用该属性的代码不驻留在属性或装饰类中,它在将使用装饰的服务层中实现.

假设我们有一个类,它返回一个类的可能显示标签:

type
  TArtifactInspector = class
  public
    class function DisplayLabelFor(aClass: TClass): string;
  end;
Run Code Online (Sandbox Code Playgroud)

如果存在,该方法将检查一个类并返回其显示标签.否则返回一个空字符串:

implementation

uses
  Rtti;

class function TArtifactInspector.DisplayLabelFor(aClass: TClass): string;
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 TDisplayLabelAttribute then
        Exit(TDisplayLabelAttribute(attribute).Text);
    Result := '';
  finally
    rttiContext.Free;
  end; // try to recover and return the DisplayLabel
end;
Run Code Online (Sandbox Code Playgroud)