home *** CD-ROM | disk | FTP | other *** search
- unit DnXmlPropMapper;
-
- interface
-
- uses
- Classes, SysUtils, TypInfo;
-
- type
- {:Baseclass to derive your custom property mapper from. Object properties must be sorted so the
- readonly properties come first.}
- TDnXmlPropMapper = class
- private
- FObject: TObject;
- FStoreReadOnlyProps: Boolean;
- protected
- function GetCount: Integer; virtual; abstract;
- function GetIsStored(aIndex: Integer): Boolean; virtual; abstract;
- function GetValue(aIndex: Integer): string; virtual; abstract;
- procedure SetValue(aIndex: Integer; const Value: string); virtual; abstract;
- function GetPropName(aIndex: Integer): string; virtual; abstract;
- function GetIsObject(aIndex: Integer): Boolean; virtual; abstract;
- function GetIsAssignableObject(aIndex: Integer): Boolean; virtual; abstract;
- function GetIsRef(aIndex: Integer): Boolean; virtual; abstract;
- function GetObjectProp(aIndex: Integer): TObject; virtual; abstract;
- procedure SetObjectProp(aIndex: Integer; const Value: TObject); virtual; abstract;
- property TheObject: TObject read FObject;
- public
- {:Always use this constructor instead of the standard one! It takes the
- object of which the properties are needed.}
- constructor CreateWithObject(aObject: TObject); overload; virtual;
- property Count: Integer read GetCount;
- property IsStored[aIndex: Integer]: Boolean read GetIsStored;
- property Value[aIndex: Integer]: string read GetValue write SetValue;
- property PropName[aIndex: Integer]: string read GetPropName;
- property StoreReadOnlyProps: Boolean read FStoreReadOnlyProps write FStoreReadOnlyProps;
- // object specific
- property ObjectProp[aIndex: Integer]: TObject read GetObjectProp write SetObjectProp;
- property IsObject[aIndex: Integer]: Boolean read GetIsObject;
- property IsAssignableObject[aIndex: Integer]: Boolean read GetIsAssignableObject;
- property IsRef[aIndex: Integer]: Boolean read GetIsRef;
- end;
-
- TDnXmlRttiPropMapper = class(TDnXmlPropMapper)
- private
- FProps: TList;
- FPropKinds: TTypeKinds;
- function Props(aIndex: Integer): PPropInfo;
- procedure UpdateProps;
- procedure SetPropKinds(const Value: TTypeKinds);
- protected
- function GetCount: Integer; override;
- function GetIsStored(aIndex: Integer): Boolean; override;
- function GetValue(aIndex: Integer): string; override;
- procedure SetValue(aIndex: Integer; const Value: string); override;
- function GetPropName(aIndex: Integer): string; override;
- // object specific
- function GetIsObject(aIndex: Integer): Boolean; override;
- function GetIsAssignableObject(aIndex: Integer): Boolean; override;
- function GetIsRef(aIndex: Integer): Boolean; override;
- function GetObjectProp(aIndex: Integer): TObject; override;
- procedure SetObjectProp(aIndex: Integer; const Value: TObject); override;
- public
- constructor CreateWithObject(aObject: TObject); override;
- destructor Destroy; override;
- {:Which kind of properties to map. Kind not in the list will not be mapped.}
- property PropKinds: TTypeKinds read FPropKinds write SetPropKinds default tkProperties;
- end;
-
- TDnXmlPropMapperClass = class of TDnXmlPropMapper;
-
- {:Returns the property mapper associated with a certain class. 0 <= aIndex < GetXmlPropMapperCount().}
- function GetXmlPropMapper(aClass: TClass; aIndex: Integer): TDnXmlPropMapperClass;
- {:Returns the number of property mappers associated with a certain class.}
- function GetXmlPropMapperCount(aClass: TClass): Integer;
- {:Registers (associates) a property mapper to a certain component class. The class must be derived from
- TComponent.}
- procedure RegisterPropMapper(aClass: TComponentClass; aMapper: TDnXmlPropMapperClass);
- {:Unregisters the propmapper (registered using the RegisterPropMapper routine) for a specific class.}
- procedure UnregisterPropMapperForClass(aClass: TComponentClass; aMapper: TDnXmlPropMapperClass);
- {:Unregisters the propmapper (registered using the RegisterPropMapper routine) for all classes it was associated with.}
- procedure UnregisterPropMapper(aMapper: TDnXmlPropMapperClass);
-
- implementation
-
- uses
- Contnrs;
-
- var
- uClasses: TList = nil; { of TClass }
- uMappers: TObjectList = nil; { of TList of TDnXmlPropMapperClass }
-
- function GetXmlPropMapper(aClass: TClass; aIndex: Integer): TDnXmlPropMapperClass;
- var idx: Integer;
- begin
- result := nil;
- for idx := 0 to uClasses.Count - 1 do
- begin
- if aClass.InheritsFrom(uClasses[idx]) then
- begin
- if aIndex < TList(uMappers[idx]).Count then
- result := TList(uMappers[idx])[aIndex]
- else
- Dec(aIndex, TList(uMappers[idx]).Count);
- end;
- end;
- end;
-
- function GetXmlPropMapperCount(aClass: TClass): Integer;
- var idx: Integer;
- begin
- result := 0;
- for idx := 0 to uClasses.Count - 1 do
- begin
- if aClass.InheritsFrom(uClasses[idx]) then
- begin
- result := result + TList(uMappers[idx]).Count;
- end;
- end;
- end;
-
- procedure RegisterPropMapper(aClass: TComponentClass; aMapper: TDnXmlPropMapperClass);
- var idx: Integer;
- mappers: TList;
- begin
- Assert(aClass <> nil);
- Assert(aMapper <> nil);
-
- idx := uClasses.IndexOf(aClass);
- if idx <> -1 then
- mappers := TList(uMappers[idx])
- else
- begin
- mappers := TList.Create;
- uMappers.Add(mappers);
- uClasses.Add(aClass);
- end;
-
- mappers.Add(aMapper);
- end;
-
- procedure UnregisterPropMapperForClass(aClass: TComponentClass; aMapper: TDnXmlPropMapperClass);
- var idx: Integer;
- mappers: TList;
- begin
- Assert(aClass <> nil);
-
- if aClass <> nil then
- begin
- idx := uClasses.IndexOf(aClass);
- if idx = -1 then
- raise Exception.CreateFmt('There was no mapper registered for class %s', [aClass.ClassName]);
- mappers := TList(uMappers[idx]);
- mappers.Remove(aMapper);
- if mappers.Count = 0 then
- begin
- uClasses.Delete(idx);
- uMappers.Delete(idx);
- end
- end;
- end;
-
- procedure UnregisterPropMapper(aMapper: TDnXmlPropMapperClass);
- var idx: Integer;
- mappers: TList;
- begin
- Assert(aMapper <> nil);
-
- idx := 0;
- while idx < uMappers.Count - 1 do
- begin
- mappers := TList(uMappers[idx]);
- mappers.Remove(aMapper);
- if mappers.Count = 0 then
- begin
- uMappers.Delete(idx);
- uClasses.Delete(idx);
- end
- else
- inc(idx);
- end;
- end;
-
- { TDnXmlPropMapper }
-
- constructor TDnXmlPropMapper.CreateWithObject(aObject: TObject);
- begin
- inherited Create;
- Assert(aObject <> nil);
- FObject := aObject;
- end;
-
- { TDnXmlRttiPropMapper }
-
- constructor TDnXmlRttiPropMapper.CreateWithObject(aObject: TObject);
- begin
- inherited;
- FPropKinds := tkProperties;
- UpdateProps;
- end;
-
- destructor TDnXmlRttiPropMapper.Destroy;
- begin
- FProps.Free;
- inherited;
- end;
-
- function TDnXmlRttiPropMapper.GetCount: Integer;
- begin
- result := FProps.Count;
- end;
-
- function TDnXmlRttiPropMapper.GetIsObject(aIndex: Integer): Boolean;
- begin
- result := Props(aIndex).PropType^.Kind = tkClass;
- end;
-
- function TDnXmlRttiPropMapper.GetIsStored(aIndex: Integer): Boolean;
- begin
- result := IsStoredProp(TheObject, FProps[aIndex]);
- if result then
- begin
- if not StoreReadOnlyProps then
- begin
- if not IsObject[aIndex] then
- result := Assigned(Props(aIndex).SetProc);
- end;
- end;
- end;
-
- function TDnXmlRttiPropMapper.GetPropName(aIndex: Integer): string;
- begin
- result := Props(aIndex).Name;
- end;
-
- function TDnXmlRttiPropMapper.GetValue(aIndex: Integer): string;
- begin
- Assert(not IsObject[aIndex]);
- result := GetPropValue(TheObject, PropName[aIndex]);
- end;
-
- procedure TDnXmlRttiPropMapper.SetValue(aIndex: Integer; const Value: string);
- begin
- Assert(not IsObject[aIndex]);
- SetPropValue(TheObject, PropName[aIndex], Value);
- end;
-
- function TDnXmlRttiPropMapper.GetObjectProp(aIndex: Integer): TObject;
- begin
- Assert(IsObject[aIndex]);
- result := TObject(GetOrdProp(TheObject, FProps[aIndex]));
- end;
-
- procedure TDnXmlRttiPropMapper.SetObjectProp(aIndex: Integer; const Value: TObject);
- begin
- Assert(IsAssignableObject[aIndex]);
- SetOrdProp(TheObject, FProps[aIndex], Integer(Value));
- end;
-
- function TDnXmlRttiPropMapper.GetIsRef(aIndex: Integer): Boolean;
- begin
- Assert(IsObject[aIndex]);
-
- if GetObjectProp(aIndex) is TComponent then
- result := TComponent(ObjectProp[aIndex]).Owner <> TheObject
- else
- result := False;
- end;
-
- function TDnXmlRttiPropMapper.GetIsAssignableObject(
- aIndex: Integer): Boolean;
- begin
- Assert(IsObject[aIndex]);
- result := Assigned(Props(aIndex).SetProc);
- end;
-
- function TDnXmlRttiPropMapper.Props(aIndex: Integer): PPropInfo;
- begin
- result := PPropInfo(FProps[aIndex]);
- end;
-
- procedure TDnXmlRttiPropMapper.UpdateProps;
- var temp: PPropList;
- count,i: Integer;
- begin
- count := GetTypeData(FObject.ClassInfo).PropCount;
- GetMem(temp, count * SizeOf(PPropInfo));
- try
- GetPropInfos(FObject.ClassInfo, temp);
-
- FProps := TList.Create;
- // filter props
- for i := 0 to count - 1 do
- begin
- if temp[i].PropType^.Kind in PropKinds then
- FProps.Add(temp[i]);
- end;
- finally
- FreeMem(temp);
- end;
- end;
-
- procedure TDnXmlRttiPropMapper.SetPropKinds(const Value: TTypeKinds);
- begin
- if FPropKinds <> Value then
- begin
- FPropKinds := Value;
- UpdateProps;
- end;
- end;
-
- initialization
- uClasses := TList.Create;
- uMappers := TObjectList.Create;
- RegisterPropMapper(TComponent, TDnXmlRttiPropMapper);
-
- finalization
- uClasses.Free;
- uMappers.Free;
- UnRegisterPropMapper(TDnXmlRttiPropMapper);
-
- end.
-