Invoke method dynamically in VB.Net SAP Business One - invoke

I have a issue with my declation when i use invoke of method as MethodInfo type:
The error message:
object reference not set to an instance of an object.
Dim oMethod As MethodInfo
oMethod = _StepInfo.CurrSysType.GetMethod(Me._MethodToRun, _MemberAccess)
'calling method on object by reflection
Dim dStart As DateTime = DateTime.Now
Dim iRes As Integer = 0
iRes = CInt(oMethod.Invoke(_StepInfo.CurrObj, Nothing))
Dim dEnd As DateTime = DateTime.Now
System.Diagnostics.Debug.WriteLine("Processing Object: " & (dEnd - dStart).TotalMilliseconds) </i>

I'm not a Reflection expert in VB, but are you sure that _StepInfo.CurrObj has been initialized and is not null? You need a valid initialized instance of your object to use Invoke, otherwise you might get a null reference exception like you're getting.
Edit:
Also, it might help to see the code where you initialize _StepInfo.CurrObj, _MethodToRun and _MemberAccess.

Related

Runtime Generated EventHandler of Unknown Type

Ok, so I have been stuck on this for a while, combining various question solutions from on here.
Situation:
I instantiate an Object of Type x by using the activator.CreateInstance(x)
Type x can vary but always has the same properties and methods.
The problem is that type x has an event ReadCompleted as ReadCompleted (this is a delegate), type y has the same event, with the same delegate but it is of type ReadCompleted1, z => ReadCompleted2, etc...
Solution:
I assign a delegate at runtime using the following code:
Dim Client As Object = ServiceProvider.GetService(TypeDict(Entity))
Dim TaskCompletionSource As New TaskCompletionSource(Of Entity)()
Dim addMethod As MethodInfo = Client.GetType().GetMethod("add_ReadCompleted")
Dim removeMethod As MethodInfo = Client.GetType().GetMethod("remove_ReadCompleted")
Dim self As Object = Nothing
Dim getSelf As Func(Of Object) = Function() self
Dim eventArgType As Type = Client.GetType().GetEvent("ReadCompleted").EventHandlerType.GetMethod("Invoke").GetParameters()(1).ParameterType
Dim e As ParameterExpression = Expression.Variable(eventArgType)
Dim ExpBlock As BlockExpression = Expression.Block({Expression.Parameter(GetType(Object)), e},
Expression.Call(
Nothing,
Me.GetType().GetMethod("ProcessTask"),
Expression.Convert(e, eventArgType),
Expression.Constant(TaskCompletionSource)),
Expression.Call(
Expression.Constant(Client),
removeMethod,
Expression.Convert(
Expression.Invoke(
Expression.Constant(getSelf)),
addMethod.GetParameters()(0).ParameterType)
)
)
Dim lambda As LambdaExpression = Expression.Lambda(
addMethod.GetParameters()(0).ParameterType,
ExpBlock,
Expression.Parameter(GetType(Object)),
Expression.Parameter(eventArgType))
Dim dlg As [Delegate] = lambda.Compile()
self = dlg
addMethod.Invoke(Client, {dlg})
Client.ReadAsync(PrimaryKey)
Now my knowledge on linq and it's Expression class is limited and i did my best to research the msdn documentation but i can't figure it out:
the method ProcessTask gets called properly, for which i've worked long enough, but my parameter e is always Nothing, resulting in a NullReferenceException.
The method:
Public Shared Sub ProcessTask(ByVal e, ByRef tcs)
'Console.WriteLine(e.GetType())
If e.Error IsNot Nothing Then
tcs.TrySetException(e.Error)
ElseIf e.Cancelled Then
tcs.TrySetCanceled()
Else
tcs.TrySetResult(e.Result)
End If
End Sub
I have no idea why, according to how i see it this is the correct way to call my method, but obviously it isn't. Can someone point me in the right direction for this?
Could be I'm just plain blind and missing something very obvious....
Thanks in advance!
EDIT:
Whilst awaiting an answer i tried to do some more debugging(which is hell in this scenario) saw that if i do:
Dim s As ParameterExpression = Expression.Variable(GetType(Object), "Sender")
Dim ExpBlock As BlockExpression = Expression.Block({s, e},
Expression.Call(
Nothing,
GetType(Console).GetMethod("WriteLine", New Type() {GetType(String)}),
Expression.Call(s, GetType(Object).GetMethod("ToString"))),
Expression.Call(
Expression.Constant(Client),
removeMethod,
Expression.Convert(
Expression.Invoke(
Expression.Constant(getSelf)),
addMethod.GetParameters()(0).ParameterType)
))
The sender as object parameter is also nothing, so i'm getting the feeling that none of my arguments are getting passed through...
Hope this helps shed more light on the matter.
I figured it out, turns out i misinterpreted the whole parameter thing of Expression:
Dim Client As Object = ServiceProvider.GetService(TypeDict(Entity))
Dim TaskCompletionSource As New TaskCompletionSource(Of Entity)()
Dim addMethod As MethodInfo = Client.GetType().GetMethod("add_ReadCompleted")
Dim removeMethod As MethodInfo = Client.GetType().GetMethod("remove_ReadCompleted")
Dim self As Object = Nothing
Dim getSelf As Func(Of Object) = Function() self
Dim eventArgType As Type = Client.GetType().GetEvent("ReadCompleted").EventHandlerType.GetMethod("Invoke").GetParameters()(1).ParameterType
Dim s As ParameterExpression = Expression.Parameter(GetType(Object), "Sender")
Dim e As ParameterExpression = Expression.Variable(eventArgType, "EventArgs")
Dim ExpBlock As BlockExpression = Expression.Block(\*{Expression.Parameter('GetType(Object)), e},*\ <--- this has to go
Expression.Call(
Nothing,
Me.GetType().GetMethod("ProcessTask"),
Expression.Convert(e, eventArgType),
Expression.Constant(TaskCompletionSource)),
Expression.Call(
Expression.Constant(Client),
removeMethod,
Expression.Convert(
Expression.Invoke(
Expression.Constant(getSelf)),
addMethod.GetParameters()(0).ParameterType)
)
)
Dim lambda As LambdaExpression = Expression.Lambda(
addMethod.GetParameters()(0).ParameterType,
ExpBlock,
s,
e)
\*Expression.Parameter(GetType(Object)),
Expression.Parameter(eventArgType))*\ <-- this has to change
Dim dlg As [Delegate] = lambda.Compile()
self = dlg
addMethod.Invoke(Client, {dlg})
Client.ReadAsync(PrimaryKey)
So as i see it the parameters don't have to be defined in the expression itself, but they sould be created, and the reference should be kept to use them in the lambda in which you compile the expression.
Hope someone in the future has some use for this answer, and thanks to all for taking a look at this.

How to read the returned complex object values when calling a method by reflection using 'Invoke' in VB.net

As you can see in the picture I see the return values from the call but I cannot use them.
How can I convert the return object to something else. This function is dynamic so I cannot use a reference object for this class.
Thank you!
I managed to read the object by using this
Dim oResults As Object = oMethod.Invoke(oUbCustomerService, oParameterValues)
For Each oResult in oResults
Dim oFieldInfoList() As FieldInfo = oResult.GetType().GetFields
dim strValue as String = oFieldInfoList(n).GetValue(oResult)
...
Next

VB Web Service call error Object reference not set

Hey all I am trying to figure out why I am getting the following error:
Object reference not set to an instance of an object.
on line 2 of code:
1. Dim HTPCws As HTPCWS.ServiceVB
2. Dim returned As String = HTPCws.DisplayMessageVB(what2send)
When I know what2send does have a value to send....
The Web Service code is this:
<WebMethod()> Public Function DisplayMessageVB(ByVal beingSent As String) As String
_strfromws = beingSent
Return "DONE"
End Function
What could I be forgetting?
HTPCws has not been instantiated. Change the code to:
Dim HTPCws = New HTPCWS.ServiceVB()
Dim returned As String = HTPCws.DisplayMessageVB(what2send)
Dim HTPCws As HTPCWS.ServiceVB declares a variable but does not assign it an object. Also the naming is a bit confusing. Better:
Dim service = New HTPCWS.ServiceVB()
Dim returned As String = service.DisplayMessageVB(what2send)

Object Reference casting vb.net

I have no idea on how to cast an object that type was 'Object' to a user defined class type.
I have a private instance variable:
Private studyType as Object
What i need to do is to instantiate this object from an event handling method. And no, not to instance new Object().
Basically it would look like this:
studyType = new VCEOnly()
However, I am only allowed to use the Object class subs and functions as the type was defined as Object. So i need to cast it to VCEOnly class type so i can access its subs and functions.
Basically, studyType needs to be casted from Object to VCEOnly. I am not allowed to pre-define studyType as VCEOnly when declared.
you can also use:
dim studyType as Object = new VCEOnly()
...
dim studyTypeVCE as VCEOnly = nothing
if trycast(studytype,VCEOnly) IsNot Nothing then
studyTypeVCE = DirectCast(studytype,VCEOnly)
'... do your thing
end if
the if statement checks if the object can be casted to the wanted type and if so variable of type VCEOnly will be filled in with a cast of studytype.
Use CType to cast an object from one type to another
Something like this should do it:
Dim studyType as Object
Dim studyTypeVCE as New VCEOnly
studyTypeVCE = Ctype(studyType,VCEOnly)
or you can just do this:
With CType(studyType, VCEOnly)
.SomeVCEOnlyProperty = "SomeValue"
End With

Unable to solve error "reference to a non-shared member requires an object reference. vb.net "

I have the following code
Case "Formula_MDX"
Dim cubeid As String = Request("intCubeId")
Dim strDimCode As String = Request("strDimCode")
Dim strMdxFormula As String = Request("strMdxFormula")
Dim result As String
result = HostAnalytics.HostAnalyzer.HostAnalyzer.setSubstituteVarMDXType(cubeid, strDimCode, strMdxFormula)
Case Else
Response.Write("Invalid call")
End Select
that vb method returns data of type string.
I declared the result of the typed string. but it is showing on that vb method like
"reference to a non-shared member requires an object reference"
How to solve this? Did I make any other mistakes in this code?
Make an object of that type, and invoke the method on that
Dim ha As New HostAnalytics.HostAnalyzer.HostAnalyzer() 'Edit, need New
result = ha.setSubstituteVarMDXType(cubeid, strDimCode, strMdxFormula)