|
From: <wp...@us...> - 2009-12-21 09:14:00
|
Revision: 880
http://instantobjects.svn.sourceforge.net/instantobjects/revision/?rev=880&view=rev
Author: wp2udk
Date: 2009-12-21 09:13:48 +0000 (Mon, 21 Dec 2009)
Log Message:
-----------
Added support for Custom Attributes in InstantObjects. In the future this initiative (custom attributes) might replace Metadata comments (See post "info: Fix for Delphi 2010 Custom Attributes"). This is a fairly new implementation and it NEEDS a great amount of DESIGN and TEST. Below you'll see a code example on how things might be implemented in the future.
Model implementation:
TContact = class(TInstantObject)
{IOMETADATA stored;
Address: Part(TAddress);
Name: String(30);
Phones: Parts(TPhone); }
[IOATTRIBUTE(atPart, -1, TAddress)]
_Address: TInstantPart;
[IOATTRIBUTE(atString, 30, nil)]
_Name: TInstantString;
[IOATTRIBUTE(atParts, -1, TPhone)]
_Phones: TInstantParts;
private
function GetAddress: TAddress;
function GetName: string;
function GetPhoneCount: Integer;
function GetPhones(Index: Integer): TPhone;
procedure SetAddress(Value: TAddress);
procedure SetName(const Value: string);
procedure SetPhones(Index: Integer; Value: TPhone);
public
function AddPhone(Phone: TPhone): Integer;
procedure ClearPhones;
procedure DeletePhone(Index: Integer);
function IndexOfPhone(Phone: TPhone): Integer;
procedure InsertPhone(Index: Integer; Phone: TPhone);
function RemovePhone(Phone: TPhone): Integer;
property PhoneCount: Integer read GetPhoneCount;
property Phones[Index: Integer]: TPhone read GetPhones write SetPhones;
published
property Address: TAddress read GetAddress write SetAddress;
property Name: string read GetName write SetName;
end;
Custom Attribute implementation:
IOATTRIBUTE = class(TInstantRttiFieldAttribute)
private
FAttributeType: TInstantAttributeType;
FDataSize: Integer;
FRef: TInstantObjectClass;
protected
procedure InternalChange(AObject: TInstantObject; AField: TRttiField); override;
public
constructor Create(AAttributeType: TInstantAttributeType; ADataSize: Integer;
ARef: TInstantObjectClass = nil);
property AttributeType: TInstantAttributeType read FAttributeType write FAttributeType;
property DataSize: Integer read FDataSize write FDataSize;
property ARef: TInstantObjectClass read FRef write FRef;
end;
implementation
{ IOATTRIBUTE }
constructor IOATTRIBUTE.Create(AAttributeType: TInstantAttributeType;
ADataSize: Integer; ARef: TInstantObjectClass = nil);
begin
FAttributeType := AAttributeType;
FDataSize := ADataSize;
FRef := ARef;
end;
procedure IOATTRIBUTE.InternalChange(AObject: TInstantObject;
AField: TRttiField);
var
Attribute: TInstantAttribute;
begin
inherited;
Attribute := AField.GetValue(AObject).AsObject as TInstantAttribute;
with Attribute.Metadata do
begin
AttributeType := FAttributeType;
DataSize := FDataSize;
if FAttributeType in [atPart, atParts, atReference, atReferences] then
ObjectClassName := FRef.ClassName;
end;
end;
Modified Paths:
--------------
trunk/Source/Core/InstantPersistence.pas
Added Paths:
-----------
trunk/Source/Core/InstantRttiAttributes.pas
Modified: trunk/Source/Core/InstantPersistence.pas
===================================================================
--- trunk/Source/Core/InstantPersistence.pas 2009-12-21 04:52:06 UTC (rev 879)
+++ trunk/Source/Core/InstantPersistence.pas 2009-12-21 09:13:48 UTC (rev 880)
@@ -1610,6 +1610,9 @@
{$ELSE}
Mask,
{$ENDIF}
+{$IFDEF D14+}
+ RTTI, InstantRttiAttributes,
+{$ENDIF}
InstantUtils, {InstantRtti, }InstantDesignHook, InstantCode;
var
@@ -2440,7 +2443,48 @@
end;
procedure TInstantAttribute.Initialize;
+
+{$IFDEF D14+}
+ procedure InitializeRttiAttributes;
+
+ procedure InvokeRttiAttribute(RttiMember: TRttiMember);
+ var
+ CustomAttribute: TCustomAttribute;
+ begin
+ for CustomAttribute in RttiMember.GetAttributes do
+ if CustomAttribute is TInstantRttiAttribute then
+ TInstantRttiAttribute(CustomAttribute).Change(Self, RttiMember);
+ end;
+
+ var
+ RttiContext: TRttiContext;
+ RttiType: TRttiType;
+ RttiField: TRttiField;
+ RttiMethod: TRttiMethod;
+ RttiProperty: TRttiProperty;
+ begin
+ RttiContext := TRttiContext.Create;
+ try
+ RttiType := RttiContext.GetType(Self.ClassType);
+
+ for RttiField in RttiType.GetFields do
+ InvokeRttiAttribute(RttiField);
+
+ for RttiMethod in RttiType.GetMethods do
+ InvokeRttiAttribute(RttiMethod);
+
+ for RttiProperty in RttiType.GetProperties do
+ InvokeRttiAttribute(RttiProperty);
+ finally
+ RttiContext.Free
+ end;
+ end;
+{$ENDIF}
+
begin
+{$IFDEF D14+}
+ InitializeRttiAttributes;
+{$ENDIF}
end;
procedure TInstantAttribute.ReadName(Reader: TInstantReader);
Added: trunk/Source/Core/InstantRttiAttributes.pas
===================================================================
--- trunk/Source/Core/InstantRttiAttributes.pas (rev 0)
+++ trunk/Source/Core/InstantRttiAttributes.pas 2009-12-21 09:13:48 UTC (rev 880)
@@ -0,0 +1,94 @@
+(*
+ * InstantObjects
+ * Delphi 2010 Custom Attributes framework
+ *)
+
+(* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is: Brian Andersen
+ *
+ * The Initial Developer of the Original Code is: Seleqt
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2001-2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brian Andersen
+ *
+ * ***** END LICENSE BLOCK ***** *)
+
+unit InstantRttiAttributes;
+
+interface
+
+uses
+ InstantPersistence, Rtti;
+
+type
+ TInstantRttiAttribute = class(TCustomAttribute)
+ public
+ procedure Change(AObject: TInstantObject; AMember: TRttiMember); virtual; abstract;
+ end;
+
+ TInstantRttiAttributeClass = class of TInstantRttiAttribute;
+
+ TInstantRttiFieldAttribute = class(TInstantRttiAttribute)
+ protected
+ procedure InternalChange(AObject: TInstantObject; AField: TRttiField); virtual; abstract;
+ public
+ procedure Change(AObject: TInstantObject; AMember: TRttiMember); override;
+ end;
+
+ TInstantRttiMethodAttribute = class(TInstantRttiAttribute)
+ protected
+ procedure InternalChange(AObject: TInstantObject; AMethod: TRttiMethod); virtual; abstract;
+ public
+ procedure Change(AObject: TInstantObject; AMember: TRttiMember); override;
+ end;
+
+ TInstantRttiPropertyAttribute = class(TInstantRttiAttribute)
+ protected
+ procedure InternalChange(AObject: TInstantObject; AProperty: TRttiProperty); virtual; abstract;
+ public
+ procedure Change(AObject: TInstantObject; AMember: TRttiMember); override;
+ end;
+
+
+implementation
+
+{ TInstantRttiFieldAttribute }
+
+procedure TInstantRttiFieldAttribute.Change(AObject: TInstantObject;
+ AMember: TRttiMember);
+begin
+ InternalChange(AObject, AMember as TRttiField);
+end;
+
+{ TInstantRttiMethodAttribute }
+
+procedure TInstantRttiMethodAttribute.Change(AObject: TInstantObject;
+ AMember: TRttiMember);
+begin
+ InternalChange(AObject, AMember as TRttiMethod);
+end;
+
+{ TInstantRttiPropertyAttribute }
+
+procedure TInstantRttiPropertyAttribute.Change(AObject: TInstantObject;
+ AMember: TRttiMember);
+begin
+ InternalChange(AObject, AMember as TRttiProperty);
+end;
+
+end.
\ No newline at end of file
Property changes on: trunk/Source/Core/InstantRttiAttributes.pas
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:eol-style
+ native
|