Home How to store different method pointers in one container in delphi?

# How to store different method pointers in one container in delphi?

Nasreddine Abdelillah Galfout
1#
Nasreddine Abdelillah Galfout Published in 2017-11-14 20:27:01Z
 I have the following method pointers type TMethod1 = procedure(aValue: TType1) of object; TMethod2 = procedure(aValue: TType2) of object; . . TMethodN = procedure(aValue: TTypeN) of object;  I want to store them in one container. I found this answer, where a pointer to TMethod1 is used to store one method and then call it. However, I would rather not use it for the following reasons: It allocates new block of memory and then later I should decide when to free it(never made it out of that area in one piece). It assumes all methods have the same definition, which is not my case. It is for one method. I have an array of them, and I do not see how I'm going to maintain such storage. And there is an example in the documentation which uses a TMethod approach, but in a different way where the second assumption above is no longer needed. In the last step to call the method, I have to do an unsafe typecast, which again is something I would like to stay away from. How do I accomplish this? Clarification on how I'm going to use these methods: I have a procedure DoWork(aData: TType1; method: TMethod1); begin store aData in a field; store method in my container; end;  Then later, process aData and call method.
Remy Lebeau
2#
Remy Lebeau Reply to 2017-11-14 22:08:33Z
 Whatever you store in your container must be the same type. You can use TMethod for that. It is a special record type provided by the RTL to represents any of object method pointer. The hard part is going to be calling the methods that are stored in your container. You can't just call TMethod directly, you have to know the exact method type that it is pointing at, then type-cast it to that type. For example: var Field: TObject; // assuming TType... are class types Container: TList; procedure DoWork(aData: T; method: procedure(aValue: T) of object); var M: TMethod; begin M := TMethod(method); Field := aData; Container.Add(M); end; procedure CallFieldMethod; var M: TMethod; begin M := Container[Index]; if Field.ClassType = TType1 then begin TMethod1(M)(TType1(Field)); end else if Field.ClassType = TType2 then begin TMethod2(M)(TType2(Field)); end ... end; ... procedure TSomeClass.MethodForType1(aValue: TType1); begin // use aValue as needed... end; DoWork(Type1Obj, MethodForType1); ... procedure TSomeClass.MethodForType2(aValue: TType2); begin // use aValue as needed... end; DoWork(Type2Obj, MethodForType2); ...  Another solution is to not rely on specific types at all, and just define 1 method type for the container. Let the caller of DoWork() decide what to do: type TMyMethod = procedure(aValue: Pointer) of object; var Field: Pointer; Container: TList; procedure DoWork(aData: Pointer; method: TMyMethod); begin Field := aData; Container.Add(method); end; procedure CallFieldMethod; begin Container[Index](Field); end; ... procedure TSomeClass.MethodForType1(aValue: Pointer); begin // use TType1(aValue) as needed... end; DoWork(Type1Obj, MethodForType1); ... procedure TSomeClass.MethodForType2(aValue: Pointer); begin // use TType2(aValue) as needed... end; DoWork(Type2Obj, MethodForType2); ... 
 You need to login account before you can post.
Processed in 0.327217 second(s) , Gzip On .