Friday, April 08, 2005

OPF.Value Type Framework

" class="oa" bg nowrap="nowrap" width="1%">Joanna Carter (TeamB) Aug 25 2004, 9:17 am
Newsgroups: borland.public.delphi.oodesign
From: "Joanna Carter \(TeamB\)"
Date: Wed, 25 Aug 2004 17:17:33 +0100
Local: Wed, Aug 25 2004 9:17 am
Subject: Re: Attribute Framework

"Hechicero" > a écrit dans le message de news:
412c9...@newsgroups.borland.com...

> Many times in this group I heard about the concept of an Attribute
> Framework. Unfortunatelly I don't know what that is and what it is used
for.
> Information I found in google didn't seem to clarify the concepto.
> Can anyone explain what an attribute framework is?

I now call it a Value Type framework as it avoids conflicts with the .NET
idea of Attributes.

Essentially it is a sophisticated version of RTTI that allows you to
implement metadata accessible without having to make all properties
published.

First, you need a simple metadata type...

IMetadata = interface
[GUID]
function GetName: string;
function GetType: TValueTypeType;
end;

...then you can add type specific additional data...

IStringMetadata = interface(IMetadata)
[GUID]
function GetLength: Integer;
function GetCase: TStringCase;
end;

IFloatMetadata = interface(IMetadata)
[GUID]
function GetSize: Integer;
function GetPrecision: Integer;
end;

Then comes the main Value Type types from which all business objects are
built...

IValueType = interface
[GUID]
procedure Assign(const Other: IValueType);
function Clone: IValueType;
function GetAsString: string;
function GetFormatString: string;
function GetMetadata: IMetadata;
function GetName: string;
function GetRequired: Boolean;
function IsNull: Boolean;
procedure SetAsString(const Value: string);
procedure SetFormatString(const Value: string);
procedure SetNull;
procedure SetRequired(Value: Boolean);
property AsString: string
read GetAsString
write SetAsString;
property FormatString: string
read GetFormatString
write SetFormatString;
property Required: Boolean
read GetRequired
write SetRequired;
end;

Once again, we can add type specific information to the generic case.

e.g.

IIntegerValueType = interface(IValueType)
[GUID]
function GetValue: Integer;
procedure SetValue(Value: Integer);
property Value: Integer
read GetValue
write SetValue;
end;

IStringValueType = interface(IValueType)
[GUID]
function GetValue: string;
procedure SetValue(const Value: string);
property Value: string
read GetValue
write SetValue;
end;

All Business Objects that contain properties/attributes are derived from
IObjectValueType, which is designed to contain a list of Value Types, one
for each property about which you wish to obtain metadata...

IObjectValueType = interface(IValueType)
[GUID]
function GetValueType(const Name: string): IValueType;
function GetValueTypes: IValueTypeList;
function GetType: TGUID;
function GetValue: IInterface;
property Value: IInterface
read GetValue;
end;

Finally, you can build something like a Customer interface and class...

ICustomer = interface
[GUID]
function GetCode: string;
function GetName: string;
function GetTotalOnOrder: Double;
function GetTotalShipped: Double;
procedure SetCode(const Value: string);
procedure SetName(const Value: string);
procedure SetTotalOnOrder(Value: Double);
procedure SetTotalShipped(Value: Double);
property Code: string
read GetCode
write SetCode;
property Name: string
read GetName
write SetName;
property TotalOnOrder: Double
read GetTotalOnOrder
write SetTotalOnOrder;
property TotalShipped: Double
read GetTotalShipped
write SetTotalShipped;
end;

TCustomer = class(TObjectValueType, ICustomer)
private
// ICustomer
function GetCode: string;
function GetName: string;
function GetTotalOnOrder: Double;
function GetTotalShipped: Double;
procedure SetCode(const Value: string);
procedure SetName(const Value: string);
procedure SetTotalOnOrder(Value: Double);
procedure SetTotalShipped(Value: Double);
end;

Property accessors usually look like this...

function TCustomer.GetName: string;
begin
Result := (GetValueTypes['Name'] as IStringValueType).Value;
end;

procedure TCustomer.SetName(const Value: string);
begin
(GetValueTypes['Name'] as IStringValueType).Value := Value;
end;

This structure allows you to address the properties of an ICustomer as
simple properties, but also as the sub value types of an object value type
complete with all their metadata.

Normal code uses the ICustomer interface, whilst OPFs and MVP frameworks can
make use of the Value Type information for persistence and display
purposes - much more sophisticated than 'data-aware'. :-))

Joanna

--
Joanna Carter (TeamB)

Consultant Software Engineer
TeamBUG support for UK-BUG
TeamMM support for ModelMaker

0 Comments:

Post a Comment

<< Home