8

how i get ownership property of Method: TRttiMethod in OnInvoke method of TVirtualInterface class?

I have this interface:

IPerson = interface(IInvokable)
   ['{45CE428C-F880-4D61-A2C1-0F3CB47130B5}']
   procedure SetName(const Value: string);
   function GetName(): string;

   [TEntityField('Field Name Here')]
   property Name: string read GetName write SetName;
end;

and this class:

type
   TVirtualEntity<T: IInvokable> = class(TVirtualInterface)
   public
      constructor Create(); reintroduce; overload;
   end;

constructor TVirtualEntity<T>.Create;
begin
   inherited Create(TypeInfo(T));
   Self.OnInvoke :=
      procedure(Method: TRttiMethod; const Args: TArray<TValue>; out Result: TValue)
      var
         attributes: TArray<TCustomAttribute>;
         attributesManager: TAttributesManager;
         entityFieldAttribute: TEntityField;
      begin
         attributesManager := TAttributesManager.Create(Method.GetAttributes);
         try                
            if attributesManager.HasAttribute<TEntityField>() then
            begin
               Result := attributesManager.GetAttribute<TEntityField>.FieldName;
            end;

         finally
            attributesManager.Free;
         end;
      end;
end;

I'd like to get TRttiProperty of Method: TRttiMethod, but how? if i change the interface to:

IPerson = interface(IInvokable)
   ['{45CE428C-F880-4D61-A2C1-0F3CB47130B5}']
   procedure SetName(const Value: string);
   [TEntityField('Field Name Here')]
   function GetName(): string;

   property Name: string read GetName write SetName;
end;

the code works, but i'd like to user interfaces like this:

IPerson = interface(IInvokable)
   ['{45CE428C-F880-4D61-A2C1-0F3CB47130B5}']
   procedure SetName(const Value: string);
   function GetName(): string;

   [TEntityField('Field Name Here')]
   property Name: string read GetName write SetName;
end;
Passella
  • 640
  • 1
  • 8
  • 23
  • small remark, dont use if assigned() and freeand nil, just call .Free (and nil assignment is also useless) – whosrdaddy Aug 25 '16 at 17:40
  • it's only a template – Passella Aug 25 '16 at 17:48
  • Your try/finally handling is a disaster. Would you like us to help you learn how to do it right. – David Heffernan Aug 25 '16 at 18:36
  • ok, sorry, i altered the code, but the point isn't this – Passella Aug 25 '16 at 19:01
  • The thing is I care about getting it right – David Heffernan Aug 25 '16 at 19:07
  • ok , I respect that , thank you for pointing out my mistake, because of that I changed the code , then someone could help me with my doubts ? – Passella Aug 25 '16 at 19:11
  • If you post a complete sample I believe you may have a workaround via the Method.parent traversing the properties. You may solve this by convention "get_" and "set_" -> matching property via parent -> reading attributes – Jasper Schellingerhout Aug 31 '16 at 15:02
  • @JasperSchellingerhout `Method.Parent` returns the interface type. So yes, you could decorate the interface with multiple attributes (one per entity field) and resolve the correct one by method naming convention. Another possibility is to just decorate the relevant methods: either with extended attributes specifying getter/setter flags, or perhaps this could be detected in code by checking if the method returns a result (getter) or not (setter). – Ondrej Kelle Sep 01 '16 at 10:41
  • I would like to user the attribute on the property , so there would have to put two attributes as in the interface , one in Method GET and another in Method SET , putting the same attribute in both methods (GET and SET) resolme the problem, but make it difficult more the use of api than simply put the attribute on the property. – Passella Sep 01 '16 at 14:31
  • 1
    @Passella I understand, but unfortunately, as I've said in my answer below, that is not possible, since there is no RTTI generated by the compiler for interface properties. Any attributes you put on interface properties are just ignored. – Ondrej Kelle Sep 02 '16 at 06:33

1 Answers1

6

Unfortunately, you can't. There is no RTTI generated for interface properties so there's nothing for your custom attribute to be attached to. Your decoration of the interface property has no effect, even if there's no warning.

Ondrej Kelle
  • 36,941
  • 2
  • 65
  • 128