2013-07-27 5 views
9

TMS Aurelius 우리는 "새로운"2010 속성 기능을 사용하여 데이터베이스 테이블 필드를 런타임에 객체 속성에 직렬화 할 수 있음을 알고 있습니다.이 딥 객체 지향 스키마의 전문가는 아니므로 살펴 봅니다. TMS 소스 코드를 직접적으로 구현하는 방법을 이해할 수 없었습니다.델파이 속성 실제 세계 예제는 어디에 있습니까?

그래서 Google의 모든 결과를 Delphi Attributes에서 찾았습니다. 모든 사람들이 게시하는 사례는 선언 사례이며 사례가 실제로 게재되기 전에 중단됩니다.

그런 다음 실제로 양식/실행 코드 내에서 juiced 클래스를 어떻게 프로젝트, 선언, 코드 및 USE 할 수 있습니까?

누구나 여기에 공유하거나 좋은 기사를 아는 예가 있습니까?

EDIT1 : 많은 있기 때문에

이 대답은 그냥 속성과 클래스 인터페이스를 보여주는 대답하지 않는, 클릭하면 생성 된 속성 클래스의 일부 사용을 실행 TButtonTForm을 가져야한다 전에 말했던 그 선언 예제들 중

+0

는 저자의 방법과 속성의 흥미로운 사용의 선언과 건설을 포함하는 전체 파일을 만들 귀찮게하지만, 우리에게 그것을 사용의에는 예제를 제공하지 않습니다 일부 텍스트가 있습니다 : 그렇지 않으면 빈 문자열을 반환합니다. – PSyLoCKe

+0

제가 관심을 보이지 않기 때문에 저는 언젠가는 똑같은 '문제'에 빠져 들었습니다. –

+4

근본적인 문제는 오랫동안 많은 사람들이 델파이 프로그래머들이 그렇게하지 못하는 데 익숙해 져서 우리가했던 방식보다 명확한 이익을 제공하는 곳을 많이 찾지 못했다는 것입니다. 많은 타사 구성 요소 공급 업체의 경우 특성을 광범위하게 사용하면 구형 델파이 버전 사용자를 대상으로하지 않으므로 시장을 더욱 제한 할 수 있습니다. – afrazier

답변

7

, 당신은 이런 식으로 작업을 수행 할 수 있습니다

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

속성은 TCustomAttribute이있는 일반 클래스입니다을 조상으로 사용합니다. 당신은 평소와 같이 그것을 구현 :

implementation 

constructor TDisplayLabelAttribute.Create(const aText: string); 
begin 
    FText := aText; 
end; 

이제 속성이 선언 및 구현

, 당신은 단지 그것을 사용할 수 있습니다

[DisplayLabel('My Class')] 
TMyClass = class 
end; 

을 이제 당신은 속성이 선언 및 구현하고 추가를 사용하고있다 어떤 클래스의 표시 레이블. 마지막 단계는 해당 속성을 사용하는 것입니다. 클래스 으로 장식했기 때문입니다. 속성을 사용하는 코드는 속성이나 데코 레이팅 된 클래스에 상주하지 않으며 장식을 사용할 서비스 계층에 구현됩니다.

의 우리가 클래스의 수 표시 레이블을 반환하는 클래스가 있다고 가정 해 봅시다 :

type 
    TArtifactInspector = class 
    public 
    class function DisplayLabelFor(aClass: TClass): string; 
    end; 

클래스를 검사하고 그 표시 라벨을 반환 방법은, 존재하는 주어진합니다.

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; 
+0

여기에 또 하나의 예제가 있습니다. http://robstechcorner.blogspot.de/2009/10/ini-persistence-rtti-way.html – Franz

+0

따라서 TObject.Create 메소드에서 객체의 속성을 설정해야합니다. 그? 델파이 사용자는 지금 당장은 필요하지 않다고 생각합니다.하지만 Java 개발자에게는 실제 비주얼 디자이너와 같은 도구가 없기 때문에 정말 필요합니다. – PSyLoCKe

+0

@EASI : 내가 제시 한 코드는 그 예입니다. 델파이에서도 속성에 대한 많은 용도가 많이 있습니다. 예를 들어, 인스턴스의 지속성을 수행하는 데 사용될 정보로 클래스를 꾸밀 수 있습니다. 이 경우 Object Inspector는 전혀 도움이되지 않습니다. 속성은 Delphi의 경우에도 언어의 중요한 개선 사항입니다. 델파이의 시각적 부분에만 의존하는 많은 프로그래머들이 흔히 간과하고 있습니다. 그러나 코드에 관해서는 속성이 큰 차이를 만들 수 있습니다. 나는 당신이 그들에 대해 마음을 열 것을 제안합니다! – AlexSC

9

나는 어떤 종류의 예제가 필요한지 잘 모르겠다. http://docwiki.embarcadero.com/RADStudio/XE4/en/Overview_of_Attributes의 IMHO는 필요한 모든 것입니다. 아마도 주석 및/또는 애스펙트 프로그래밍에 대한 기본 지식을 갖추고 있어야합니다.

예는 특정 SW 작성자가 속성을 사용하는 방식/목적에 따라 다릅니다. 당신은 ORM 시스템에 대해 언급했습니다. 일반적인 사용법은 DB 엔터티를 나타내는 클래스 멤버에게 이러한 프레임 워크의 백엔드에서 DB 작업에 필요한 추가 정보를 주석으로 추가하는 것입니다. NOT NULL 당신은 DB 엔티티 가진 필드 회사 CHAR (32)가 가정 해 봅시다 당신은 델파이 클래스를 대표 할 : 생성자

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

그리고 사용과 TCharColumn을

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

는 다음 속성을 정의합니다 같은 주석의이 같은 것을 볼 수 있었다 :

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; 

프로그램의이 작품은 델파이 주석에 따라 런타임에 데이터 집합의 필드를 정의하는 방법을 설명합니다. 우리는 명명 된 매개 변수가 부족하여 제한되어 있으므로 매개 변수 목록을 사용하면 유연하지 않습니다. 문제는 속성 사용의 실제 사례를 요구하는 경우와 같은 자바 (비교 TMS 아우렐리우스 주석이 http://www.tmssoftware.com/site/manuals/aurelius_manual.pdfhttp://www.techferry.com/articles/hibernate-jpa-annotations.html

+0

TMS ORM 사이트에서 보았던 코드에서 처음에는 어느 것이 tabe 필드인지 알지 못했기 때문에'Create' 메소드를 사용하면 프레임 워크가 데이터베이스를 읽고' MyString : = MyORM.TableName.TableField;'그리고 예제에서는'[TCharColumn ('COMPANY', 32, false)]'를 선언해야합니다. 나는 Attributes의 실제 사용에 대해 오해 했습니까? – PSyLoCKe

+0

DB 테이블을 생성하는 전통적인 접근법은 SQL 명령어 CREATE TABLE을 작성하고 SQL을 사용하여 그러한 테이블을 사용하는 것입니다. OTOH, ORM에서는 SQL 명령을 사용하지 않습니다 (** 절은 ** 절 제외). DB 테이블은 주석이 달린 클래스 (속성 포함)이며 ORM을 통해 데이터를 조작합니다. TMS는 모르지만 예를 들면 시작시 Hibernate는 주석에 관해서 RDBMS에서 DB 스키마를 처리하는 방법을 cfg로 확인합니다 : ** validate ** : 프로덕션은 diff에서 예외를 throw합니다 ** update ** : RDBMS에서 DB 스키마 업데이트를 시도합니다 (모든 것이 업데이트 될 수있는 것은 아닙니다) , ** 생성 **, ** 생성 - 드롭 ** : 기존 DB incl. 데이터를 생성하고 새로운 DB 스키마를 생성합니다 – pf1957

8

확실하지 않음을 설정 또는 속성을 사용하여 개체에 DB 테이블을 직렬화하는 방법에 대해 설명합니다. 아래의 예는 인위적인 간단한 하나입니다 (하지만 그보다 작은 예는 속성을 사용하여 객체 속성에 대한 변경 사항을 기록하는 방법을 보여줍니다.

속성

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; 

는 "loggable 속성을"이있는 모든 클래스를 사용하여 TProduct

//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; 

클래스의 "안녕하세요"사용자 정의 속성 정의 반복이 메서드에 전달 될 수있다 속성을 통해 그들을 기록합니다.

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; 

end; 사용

예 : 당신이 당신 자신의 속성을 선언 할 경우

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); 
+0

아마도 "속성을 사용하여 db 테이블을 객체로 직렬화하는 방법"으로 변경해야합니다 ... : – PSyLoCKe

+0

규칙 속성에 따라 ** 앞에 ** T가 없습니다 ** . 또한 이름의'Attribute' 부분은 주석에서 생략 될 수 있습니다. 그래서'LoggableAttribute'라는 속성은'[Loggable ('test')]'처럼 사용할 수 있습니다. – Johan

+0

TLoggableProperty 란 무엇입니까? – Mohamad