Hi,
We need to replace some Visual studio code with Progress code but I have no idea how i need to translate the following:
ExtensionManager.Instance.Invoke(Of IPaymentHandlerExtension)(Sub(x) x.HandlePayment(paymentId, amount, comment))
Can someone give me a direction?
Regards
Didier
I doubt that anyone on this forum know what "ExtensionManager.Instance.Invoke(Of IPaymentHandlerExtension)(Sub(x) x.HandlePayment(paymentId, amount, comment))” means.
You will have to supply a lot more information about your environment before anyone will be able to assist.
What OpenEdge version?
Of what software is ExtensionManager a part?
What are the datatypes being passed in the function call ?
What are the expected return values?
[quote user="DenDuze"]
Hi,
We need to replace some Visual studio code with Progress code but I have no idea how i need to translate the following:
ExtensionManager.Instance.Invoke(Of IPaymentHandlerExtension)(Sub(x) x.HandlePayment(paymentId, amount, comment))
Can someone give me a direction?
Regards
Didier
[/quote]
Not so sure if ExtensionManager Invoke method is just the System.Reflection Invoke method, but here is a sample code to dynamically invoke a class method in ABL.
DEFINE VARIABLE oMethod AS System.Reflection.MethodInfo NO-UNDO.
DEFINE VARIABLE oType AS System.TYPE NO-UNDO.
DEFINE VARIABLE bindingAttr AS BindingFlags NO-UNDO.
DEFINE VARIABLE arrayVar AS System.Object EXTENT 2 NO-UNDO.
bindingAttr = BindingFlags:Instance.
bindingAttr = CAST(EnumHelper:Or(bindingAttr, BindingFlags:NonPublic), BindingFlags).
oType = Progress.Util.TypeHelper:GetType("System.Windows.Forms.Control"). // IPaymentHandlerExtension
oMethod = oType:GetMethod("RemovePendingMessages", bindingAttr). // HandlePayment
IF VALID-OBJECT(oMethod) THEN
oMethod:Invoke(THIS-OBJECT, arrayVar).
THIS-OBJECT - is the object instance (x in your sample)
arrayVar - parameters to method you are calling
Hi Gus/jquerijero,
The problem is that I also do not know what all this does.
We need to put some existing functionality (currently written in vb) in our Progress application.
The person who implemented that functionality only executed ths following code:
' Handle payments
If RadioButtonShop.Checked = True Then
For Each row As DataGridViewRow In DataGridViewInvoicePayments.Rows
Dim amount = cVerGeneralSubsAndFunctions.ReturnSingleIfNull(DataGridViewInvoicePayments("PaymentAmount", row.Index).Value)
If amount < 0.01 Then Continue For
Dim comment = String.Format("{0}-{1}/{2}", TextBoxDocumentNumber.Text, VERPigoMainForm.strBranchCode, Strings.Right(MaskedTextBoxCustomerNumber.Text, VERPigoMainForm.intLengthCustomerNumber))
Dim paymentId = CInt(row.Cells("PaymentMethodID").Value)
ExtensionManager.Instance.Invoke(Of IPaymentHandlerExtension)(Sub(x) x.HandlePayment(paymentId, amount, comment))
Next
End If
He tells me that when he calls that ExtensionManager:instance:Invoke a form is shown where the user can make some payments.
So the easiest way for me to implement that functionality is try to do the same but I have no idea what that line of code just does (I'm no .net programmer, I understand a bit but ...)
If needed I can provide you the ExtentionManager.vb file but maybe the comment on top of that file can help
This class will scan a directory for dll's with types that implement IExtension
'Any types found are instanciated and available to call using the ExtensionMethod.Invoke(Of T) method
The Invoke method has the following code:
Public Sub Invoke(Of T)(act As Action(Of T))
For Each extension As IExtension In _extensions.Where(Function(e) GetType(t).IsAssignableFrom(e.GetType))
Dim extOfT = DirectCast(extension, T)
act(extOfT)
Next
End Sub
The IPaymentHandlerExtension has the following code:
Public Interface IPaymentHandlerExtension
Inherits IExtension
Function HandlePayment(paymentMethodId As Integer, amount As Single, comment As String) As Boolean
End Interface
There is also a class AdyenPaymentHandlerExtension that Implemants the iPaymentHandlerExtension where the HandlePayment method is implemented
For the rest there are some other files but as far as I know (hope) I do not need to know what these do because when I could replace that
ExtensionManager.Instance.Invoke(Of IPaymentHandlerExtension)(Sub(x) x.HandlePayment(paymentId, amount, comment))
It should hopefully work (that's what that person who made the vb-code said)
regards
Didier
Hi Mike,
I can only see a Telerik.WinControls.ReflectionHelper in the Class Browser.
I guess that one is only for Telerik controls.
In my case it's not a Telerik controls so ....
Regards
Didier
@Mike: ok but i guess that belongs to the consulting SmartComponent framework so i can't use that - or I'm I wrong about that? I never used something like this .
@jquerijero: I also tried your approch but the oMethod is not a valid-object so I must do something wrong here.
I used the following code to test:
define variable oMethod as System.Reflection.MethodInfo no-undo.
define variable oType as System.Type no-undo.
define variable bindingAttr as System.Reflection.BindingFlags no-undo.
define variable arrayVar as System.Object extent 3 no-undo.
bindingAttr = System.Reflection.BindingFlags:Instance.
bindingAttr = CAST(Progress.Util.EnumHelper:or(bindingAttr, System.Reflection.BindingFlags:NonPublic), System.Reflection.BindingFlags).
oType = Progress.Util.TypeHelper:GetType("Verpigo.Extensibility.IPaymentHandlerExtension").
/* here both object are valid */
message program-name(1) skip valid-object(oType) skip valid-object(bindingAttr)
view-as alert-box.
oMethod = oType:GetMethod("HandlePayment", bindingAttr). // HandlePayment
/* this gives me false back whle the function is defined there like
Function HandlePayment(paymentMethodId As Integer, amount As Single, comment As String) As Boolean */
message program-name(1) skip 'omethod ' valid-object(oMethod)
view-as alert-box.
regards
Didier
ok, tried it with that but It's unclear to me how I need to use that in my case
I tried the following method PUBLIC System.Object InvokeGenericMethod (Object, character, character)
def var o as Verpigo.Extensibility.ExtensionManager.
def var o2 as PaymentExtension_Adyen.AdyenPaymentHandlerExtension.
o2 = CAST (ReflectionHelper:InvokeGenericMethod(o,
"HandlePayment",
"Verpigo.Extensibility.ExtensionManager").
But I get error 205
I'm sure I'm doing something wrong (but that's normal because I have no idea what this does)
The code to translate is:
ExtensionManager.Instance.Invoke(Of IPaymentHandlerExtension)(Sub(x) x.HandlePayment(paymentId, amount, comment))
Please advise
o2 = CAST (ReflectionHelper:InvokeGenericMethod(o,
"HandlePayment",
"Verpigo.Extensibility.ExtensionManager"),
PaymentExtension_Adyen.AdyenPaymentHandlerExtension) .
Arrrrh, damn how stupid.
Changed it but I get
Invalid handle. Not initialized or points to deleted object (3135)
I also tried with
o2 = CAST (ReflectionHelper:InvokeGenericMethod( o,
"Invoke",
"Verpigo.Extensibility.ExtensionManager"),
PaymentExtension_Adyen.AdyenPaymentHandlerExtension).
But then I get
System.Reflection.TargetParameterCountException: Parameter count mismatch.
Like I already mentioned it's not clear to me what the original code just does:
ExtensionManager.Instance.Invoke(Of IPaymentHandlerExtension)(Sub(x) x.HandlePayment(paymentId, amount, comment)).
Maybe someone can explain me what this code just does because I tried multiple things but always get some kind of error
The Invoke methos in ExtensionManager.vb:
Public Sub Invoke(Of T)(act As Action(Of T))
For Each extension As IExtension In _extensions.Where(Function(e) GetType(t).IsAssignableFrom(e.GetType))
Dim extOfT = DirectCast(extension, T)
act(extOfT)
Next
End Sub
The HandlePayment method in AdyenPaymentHandlerExtension;vb:
Public Function HandlePayment(paymentMethodId As Integer, amount As Single, comment As String) As Boolean Implements IPaymentHandlerExtension.HandlePayment
'only handle the payment codes that are configured in the config file
If Not AcceptedPaymentMethodIds.Contains(paymentMethodId) Then
Return False
End If
Parameters = New List(Of String) From {"-a", amount.ToString(CultureInfo.InvariantCulture), "-c", comment}
Return RunProcess() = 0 'external process has to return 0 if everything is OK
End Function
So I really have no idea it that is translatable to Progress or not (and how)
Is o initialized ?
I guess it is,
I did:
def var o as Verpigo.Extensibility.ExtensionManager.
Verpigo.Extensibility.ExtensionManager:Init("C:\Users\didier.d\Desktop\test_angloParts").
o = Verpigo.Extensibility.ExtensionManager:Instance.
When I do valid-object(o) I get true back so...
Regards
Didier
As I said before. VB.NET ... what I'd suggest is that you share the link to the API documentation of the classes you're trying to access.
Now understand, Invoke is actually trying to call HandlePayment on all available matching extensions. I don't think this is translatable to ABL. The code I posted will not work; it's for a different purpose.
Specially this line will not translate:
ExtensionManager.Instance.Invoke(Of IPaymentHandlerExtension)(Sub(x) x.HandlePayment(paymentId, amount, comment)) because Sub(x) x.HandlePayment(paymentId, amount, comment) is an inline delegate definition.
The key is re-implementing Invoke to not use delegate. Basically, Invoke should look something like this;
Invoke(paymentId, amount, comment)
... You might need to iterate through all the extension and see which extension implements HandlePayment by checking if TYPE-OF is IPaymentHandlerExtension.
@Mike: As far as I know there is no documentation available.
It's a combination of a c#-project written by some guy (doesn't work there anymore) and a vb-project written by another programmer (also doesn't work there anymore) where another programmer makes a call to from on another vb-project (as far as I understand).
The latter programmer still works there but only knows that his code makes everything work fine for the last # years.
Now they want to change to our software but still want to keep using this functionality.
The easiest way to do that is by trying to translate the code of the latest vb-project (it's only a few lines) to Progress code because if we hare to re-write the whole functionality ....
Maybe you can spare some time in Dublin to take a look @this (ofcourse with some drinks nearby)
@jquerijero: I'm not sure I completely understand but what I do not understand is why I can not call that HandlePayment function directly. I also do not see how this code will make the whole thing work but ok if this worked in the past with the vb-code it should work with the Progress-code i guess.
Regards
Didier
As far as i understand it's like that.
Now thanks for the offer, I also contacted that latest vb-programmer and asked him if he can make some class that does everything that is needded and that I just can instantiate.
I will wait on that answer before I will proceed to contact our managament about your consultancy
[quote user="DenDuze"]I'm not sure I completely understand but what I do not understand is why I can not call that HandlePayment function directly. [/quote]
You should be able to if you can get the extension instance.
The problem you are facing, as I understand it, is that the extensions are loading dynamically. My suggestion is actually iterating through the dynamic instances and then check the instance type. You can save the dynamically created extension instances to a temp-table or a generic collection. While iterating, if the instance type matches iPaymentHandleExtension using TYPE-OF, then you can certainly just call HandlePayment directly using CAST. This code can replace the call to Invoke.