How get ownership property of (Method: TRttiMethod) in TVirtualInterface TVirtualInterfaceInvokeEvent?
Asked Answered
D

1

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;
Dendrochronology answered 25/8, 2016 at 17:17 Comment(10)
small remark, dont use if assigned() and freeand nil, just call .Free (and nil assignment is also useless)Nonviolence
it's only a templateDendrochronology
Your try/finally handling is a disaster. Would you like us to help you learn how to do it right.Codel
ok, sorry, i altered the code, but the point isn't thisDendrochronology
The thing is I care about getting it rightCodel
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 ?Dendrochronology
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 attributesHunker
@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).Handmaiden
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.Dendrochronology
@Dendrochronology 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.Handmaiden
H
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.

Handmaiden answered 29/8, 2016 at 15:36 Comment(1)
Actually, this is a bug, since the documentation of GetProperties states: Although GetProperties is declared in TRttiType, it only works in RTTI objects describing types that actually allow properties, such as records, classes, and interfaces; for all other types, this method simply returns an empty array.Watering

© 2022 - 2024 — McMap. All rights reserved.