-
-
Save dipold/7b871788222dd7eb94962a9cc92d2e9a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
program Project1; | |
{$APPTYPE CONSOLE} | |
{$R *.res} | |
uses | |
System.Rtti, | |
System.SysUtils, | |
System.TypInfo; | |
type | |
IFoo = interface(IInvokable) | |
['{22C53437-C1E8-4A3D-B397-4F041743AD84}'] | |
function GetValue: String; | |
procedure SetValue(const AValue: String); | |
property Value: String read GetValue write SetValue; | |
end; | |
{$RTTI EXPLICIT METHODS([vcPrivate])} | |
TFoo = class(TInterfacedObject, IFoo) | |
strict private | |
FValue: String; | |
function GetValue: String; | |
procedure SetValue(const AValue: String); | |
public | |
property Value: String read GetValue write SetValue; | |
end; | |
TProxy<T: IInvokable> = class(TVirtualInterface) | |
strict private | |
FRealInstance: T; | |
FLoaded: Boolean; | |
procedure VirtualInterfaceInvokeEvent(AMethod: TRttiMethod; const AArgs: TArray<TValue>; out OResult: TValue); | |
public | |
constructor Create(const AStubInstance: T); | |
end; | |
constructor TProxy<T>.Create(const AStubInstance: T); | |
begin | |
inherited Create(TypeInfo(T), VirtualInterfaceInvokeEvent); | |
FLoaded := False; | |
FRealInstance := AStubInstance; | |
end; | |
procedure TProxy<T>.VirtualInterfaceInvokeEvent(AMethod: TRttiMethod; const AArgs: TArray<TValue>; out OResult: TValue); | |
var | |
LContext: TRttiContext; | |
LArgs: TArray<TValue>; | |
LObject: TObject; | |
LMethod: TRttiMethod; | |
I: Integer; | |
begin | |
LArgs := Copy(AArgs, 1); | |
if (not FLoaded) then | |
begin | |
//FRealInstance := DAOManager<T>.GetFoo.FromDatabase; | |
FLoaded := True; | |
end; | |
//There are a best way to invoke AMethod from FRealInstance? | |
//It seems a little expensive to do this way | |
LObject := FRealInstance as TObject; | |
for LMethod in LContext.GetType(LObject.ClassInfo).GetMethods do | |
begin | |
if (CompareText(LMethod.Name, AMethod.Name) = 0) then | |
begin | |
if (Length(LMethod.GetParameters) = Length(AMethod.GetParameters)) then | |
begin | |
for I := 0 to Pred(Length(LMethod.GetParameters)) do | |
if (LMethod.GetParameters[I].ParamType.TypeKind <> AMethod.GetParameters[I].ParamType.TypeKind) then | |
Continue; | |
OResult := LMethod.Invoke(LObject, LArgs); | |
Break; | |
end; | |
end; | |
end; | |
end; | |
{ TFoo } | |
function TFoo.GetValue: String; | |
begin | |
Result := FValue; | |
end; | |
procedure TFoo.SetValue(const AValue: String); | |
begin | |
FValue := AValue; | |
end; | |
var | |
ProxyFoo: IFoo; | |
begin | |
ProxyFoo := TProxy<IFoo>.Create(TFoo.Create) as IFoo; | |
ProxyFoo.Value := 'Bar'; | |
WriteLn('Value: ', ProxyFoo.Value); | |
ProxyFoo.Value := 'Xyzzy'; | |
WriteLn('Value: ', ProxyFoo.Value); | |
ReadLn; | |
end. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment