InvokeMethod NullReferenceException
-
Tuesday, March 09, 2010 7:50 PM
I have a Web App that i am running into a problem. I have a DataSet called "DateTable" and an Adapter named "DateTableAdapter".
Both of these work fine if i invoke them individually and through some logic testing. What i have tried to do though is construct some logic that will build a string that represents the method to be called based on some application Enums
Dim tmpMethod As String = "Get" Dim tmpParameters() As Object tmpMethod &= core.Type.ToString If Not (core.Shift = Nothing) Then tmpMethod &= "ByShift" tmpParameters = New Object() {CType(core.Line, Byte), CType(core.Shift, Byte)} Else tmpParameters = New Object() {CType(core.Line, Byte)} End If tbDateInfo = core.InvokeMethod(Of DateTableDataTable)("prodsumTableAdapters.DateTableTableAdapter", tmpMethod, tmpParameters)
All the above works peachy, its when i get into the InvokeMethod part of things is where it goes wrong
Public Shared Function InvokeMethod(Of T As New)(ByVal typeName As String, ByVal methodName As String, ByVal param() As Object) As T Dim calledType As Type = System.Type.GetType(typeName) Dim result As Object result = calledType.InvokeMember(methodName, Reflection.BindingFlags.Public Or Reflection.BindingFlags.DeclaredOnly Or Reflection.BindingFlags.InvokeMethod Or Reflection.BindingFlags.Instance, Nothing, Nothing, param) Return CType(result, T) End Function
I have used various deviations of the ctype to encapsulate the InvokeMember section to return the T type. Still get the NullReferenceException at the InvokeMember line. Not quite sure where the problem lies in all this. The method being invoked is not a generic method and is well defined, as you see below.
The Method(s) Exist
<Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _ Global.System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter"), _ Global.System.ComponentModel.DataObjectMethodAttribute(Global.System.ComponentModel.DataObjectMethodType.[Select], true)> _ Public Overloads Overridable Function GetProduction(ByVal line As Byte) As prodsum.DateTableDataTable Me.Adapter.SelectCommand = Me.CommandCollection(0) Me.Adapter.SelectCommand.Parameters(0).Value = CType(line,Byte) Dim dataTable As prodsum.DateTableDataTable = New prodsum.DateTableDataTable Me.Adapter.Fill(dataTable) Return dataTable End Function <Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _ Global.System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter"), _ Global.System.ComponentModel.DataObjectMethodAttribute(Global.System.ComponentModel.DataObjectMethodType.[Select], false)> _ Public Overloads Overridable Function GetMaterial(ByVal line As Byte) As prodsum.DateTableDataTable Me.Adapter.SelectCommand = Me.CommandCollection(1) Me.Adapter.SelectCommand.Parameters(0).Value = CType(line,Byte) Dim dataTable As prodsum.DateTableDataTable = New prodsum.DateTableDataTable Me.Adapter.Fill(dataTable) Return dataTable End Function
Nothing but something
Answers
-
Wednesday, March 10, 2010 4:10 PM
Visual Basic
Imports System.Reflection
Module Module1
Sub Main()
InvokeMethod()
Console.ReadLine()
End Sub
Sub InvokeMethod()
Dim instance As Class1 = New Class1()
Dim args As Object() = Nothing
args = New Object(0) {"data"} ' comment out this line to invoke other method.
Dim invoker As Type = instance.GetType()
invoker.InvokeMember( _
"MethodToInvoke", _
BindingFlags.Public Or BindingFlags.Instance Or BindingFlags.InvokeMethod, _
Nothing, _
instance, _
args)
Return
End Sub
End Module
Class Class1
Sub MethodToInvoke()
Console.WriteLine("Method_01 has been invoked through Reflection.")
End Sub
Sub MethodToInvoke(ByVal obj As Object)
Console.WriteLine("Method_02 has been invoked through Reflection.")
End Sub
End Class
Mark the best replies as answers. "Fooling computers since 1971."- Marked As Answer by goldbishop Wednesday, March 10, 2010 4:52 PM
-
Wednesday, March 10, 2010 4:59 PM
just to be clear here is the final code and worked perfectly...I should just PM you Rude next time ;) Thank you as well Mario for advising me on the potential errors that were to come up as you stated.
Public Shared Function CreateInstance(ByVal [type] As Type, ByVal [class] As String, ByVal args() As Object) As Object Dim ____ As Reflection.Assembly = Reflection.Assembly.GetAssembly([type]) Try For Each t As Type In ____.GetTypes If t.IsClass = True Then If t.FullName.EndsWith("." + [class]) Then Dim con() As Reflection.ConstructorInfo = t.GetConstructors For Each constr As Reflection.ConstructorInfo In con If constr.GetParameters.Length = args.Length Then Return constr.Invoke(args) End If Next End If End If Next Return Nothing Catch ex As Exception Throw New System.Exception("could not create instance ---->" + [class]) Return Nothing End Try End Function Public Shared Function InvokeMethod(Of T)(ByVal typeName As ComponentModel.Component, ByVal methodName As String, ByVal param() As Object) As T 'Get the actual classes name for instantiation Dim [class] As String = typeName.ToString.Substring(typeName.ToString.LastIndexOf(".") + 1) 'create an instance of the object of typeName by its class alone Dim instance As Object = CreateInstance(typeName.GetType, [class], New Object() {}) 'get the type of the object Dim invoker As Type = instance.GetType Dim result As Object result = invoker.InvokeMember(methodName, Reflection.BindingFlags.Public Or Reflection.BindingFlags.Instance Or Reflection.BindingFlags.InvokeMethod, Nothing, instance, param) Return CType(result, T) End FunctionThe CreateInstance method was a code copy from another site, go here
Nothing but something- Marked As Answer by goldbishop Wednesday, March 10, 2010 5:42 PM
All Replies
-
Tuesday, March 09, 2010 8:36 PM
You passed a null value, Nothing, as the object instance on which to invoke the method.
You must call an instance method, not a static or shared method.
InvokeMember(String, BindingFlags, Binder, Object, Object [] )
Rudy =8^D
Mark the best replies as answers. "Fooling computers since 1971."- Proposed As Answer by Alex Skalozub Wednesday, March 10, 2010 2:14 PM
-
Tuesday, March 09, 2010 8:45 PM
A NullReferenceException in that context probably indicates that the type does not exist (what you store in calledType). Make sure that the type is spelled and cased correctly, and that it is fully qualified.
Once you fix that, though, you are going to get the exception (a TargetException this time) that Rudy refers to, so you better fix that too...
HTH
--mc- Proposed As Answer by Rudedog2MVP Tuesday, March 09, 2010 8:59 PM
- Unproposed As Answer by goldbishop Wednesday, March 10, 2010 2:02 PM
-
Wednesday, March 10, 2010 2:01 PM
Seems that DataAdapters are not Types. As you mentioned, the problem was in the Instance Object not being passed.
I tried several variations but was unable to get a Type reference to my TableAdapter that holds the Method.Everything is Cased correctly. But after i posted this and several hours of breakpoints :( it is ultimately failing at the calledType line.
I would assume then that a TableAdapter is not a Type but an Object only and as such can not be Type'd?
Any ideas on how to incorporate this type of logic on a non-Type'd object without having to code for each logical pattern?
Nothing but something -
Wednesday, March 10, 2010 2:23 PM
Ok finally got the NullReferenceException removed by changing the typeName type from String to Component as such.
Public Shared Function InvokeMethod(Of T)(ByVal typeName As ComponentModel.Component, ByVal methodName As String, ByVal param() As Object) As T
And as you called it, i am getting the MissingMethodException.
The new InvokeMember method now is:result = calledType.InvokeMember(methodName, Reflection.BindingFlags.Public Or Reflection.BindingFlags.DeclaredOnly Or Reflection.BindingFlags.InvokeMethod, Nothing, typeName, param)
For sake of consistency, i am trying to call the ByShift method and its declaration is:
<Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _ Global.System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter"), _ Global.System.ComponentModel.DataObjectMethodAttribute(Global.System.ComponentModel.DataObjectMethodType.[Select], false)> _ Public Overloads Overridable Function GetProductionByShift(ByVal line As Byte, ByVal shift As Byte) As prodsum.DateTableDataTable Me.Adapter.SelectCommand = Me.CommandCollection(3) Me.Adapter.SelectCommand.Parameters(0).Value = CType(line,Byte) Me.Adapter.SelectCommand.Parameters(1).Value = CType(shift,Byte) Dim dataTable As prodsum.DateTableDataTable = New prodsum.DateTableDataTable Me.Adapter.Fill(dataTable) Return dataTable End Function
And yes most of this was auto-generated while i designed the XSD.
Nothing but something -
Wednesday, March 10, 2010 2:42 PM
Did a little debug checking now that i can actually invoke the type.
Boolean get_ClearBeforeFill() Void set_ClearBeforeFill(Boolean) DateTableDataTable GetProduction(Byte) DateTableDataTable GetMaterial(Byte) DateTableDataTable GetMaterialByShift(Byte, System.Nullable`1[System.Byte]) DateTableDataTable GetProductionByShift(Byte, Byte) DateTableDataTable GetScrap(Byte) DateTableDataTable GetScrapByShift(Byte, System.Nullable`1[System.Byte]) Void add_Disposed(System.EventHandler) Void remove_Disposed(System.EventHandler) System.ComponentModel.ISite get_Site() Void set_Site(System.ComponentModel.ISite) Void Dispose() System.ComponentModel.IContainer get_Container() System.String ToString() System.Object GetLifetimeService() System.Object InitializeLifetimeService() System.Runtime.Remoting.ObjRef CreateObjRef(System.Type) Boolean Equals(System.Object) Int32 GetHashCode() System.Type GetType()
This is the full mthods list available to the Type i am trying to get from. I see the two methods that have Nullable types and will be fixing that soon, but otherwise this is exactly what should be here as far as i care.
Nothing but something -
Wednesday, March 10, 2010 2:43 PM
The message suggests that you are providing an instance object of a type that lacks the method you are trying to invoke. What type contains the method you are trying to invoke? That is the type that is required in the place of where you are using "typeName".
What do mean a TableAdapter is not a type? Sure it is. You should be able to see it in your Object Browser Window of your project. Don't ignore Mario's advice, either.
Rudy =8^D
Mark the best replies as answers. "Fooling computers since 1971." -
Wednesday, March 10, 2010 2:52 PM
I havent ignored the advice...actually his got me thinking of a different approach
i changed the typeName type from String to Component, to correctly obtain the type reference. Hence the Vote+1 ;)
Seems their reply system is a little messed up atm, so sorry for the unordered replies. I did a Debug.WriteLine iteration on the Methods that are available through the Type object and its there even with the Parameter set i am passing
Here is the core information:
param() = {Byte, Byte} methodName = "GetProductionByShift" typeName = prodsum.prodsumTableAdapters.DateTableTableAdapterEverything is correct, maybe the InvokeMember use is incorrect, but otherwise everything is going well, just cant seem to get the TableAdapter to call the method, unless i need to involve another step before the InvokeMember method. I tried using the Assembly call for the Class name to get a class object reference but it didnt work either. I am expanding my knowledge of the .Net framework with this little dig of mine.
Nothing but something -
Wednesday, March 10, 2010 2:58 PMWhat type contains the method you are trying to invoke? TableAdapter?
That is the type that is required in the place of where you are using "typeName".
Mark the best replies as answers. "Fooling computers since 1971." -
Wednesday, March 10, 2010 3:18 PM
Here's an example for a Console Application.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
InvokeMethod();
}
private static void InvokeMethod()
{
Class1 instance = new Class1();
Object[] args = null;
args = new Object[] { "data" }; // comment this line out to call other method!
Type invoker = instance.GetType();
invoker.InvokeMember(
"MethodToInvoke",
BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod,
null,
instance,
args);
Console.ReadLine();
}
}
}
public class Class1
{
public void MethodToInvoke()
{
Console.WriteLine("Method_01 has been invoked through Reflection.");
}
public void MethodToInvoke(object obj)
{
Console.WriteLine("Method_02 has been invoked through Reflection.");
}
}
Hope this helps.
Rudy =8^D
Mark the best replies as answers. "Fooling computers since 1971." -
Wednesday, March 10, 2010 4:10 PM
Visual Basic
Imports System.Reflection
Module Module1
Sub Main()
InvokeMethod()
Console.ReadLine()
End Sub
Sub InvokeMethod()
Dim instance As Class1 = New Class1()
Dim args As Object() = Nothing
args = New Object(0) {"data"} ' comment out this line to invoke other method.
Dim invoker As Type = instance.GetType()
invoker.InvokeMember( _
"MethodToInvoke", _
BindingFlags.Public Or BindingFlags.Instance Or BindingFlags.InvokeMethod, _
Nothing, _
instance, _
args)
Return
End Sub
End Module
Class Class1
Sub MethodToInvoke()
Console.WriteLine("Method_01 has been invoked through Reflection.")
End Sub
Sub MethodToInvoke(ByVal obj As Object)
Console.WriteLine("Method_02 has been invoked through Reflection.")
End Sub
End Class
Mark the best replies as answers. "Fooling computers since 1971."- Marked As Answer by goldbishop Wednesday, March 10, 2010 4:52 PM
-
Wednesday, March 10, 2010 4:13 PMSo i will need to do an Assembly Reflection to get an instance of the class built so i can pass that instance through the InvokeMember method?
Nothing but something -
Wednesday, March 10, 2010 4:59 PM
just to be clear here is the final code and worked perfectly...I should just PM you Rude next time ;) Thank you as well Mario for advising me on the potential errors that were to come up as you stated.
Public Shared Function CreateInstance(ByVal [type] As Type, ByVal [class] As String, ByVal args() As Object) As Object Dim ____ As Reflection.Assembly = Reflection.Assembly.GetAssembly([type]) Try For Each t As Type In ____.GetTypes If t.IsClass = True Then If t.FullName.EndsWith("." + [class]) Then Dim con() As Reflection.ConstructorInfo = t.GetConstructors For Each constr As Reflection.ConstructorInfo In con If constr.GetParameters.Length = args.Length Then Return constr.Invoke(args) End If Next End If End If Next Return Nothing Catch ex As Exception Throw New System.Exception("could not create instance ---->" + [class]) Return Nothing End Try End Function Public Shared Function InvokeMethod(Of T)(ByVal typeName As ComponentModel.Component, ByVal methodName As String, ByVal param() As Object) As T 'Get the actual classes name for instantiation Dim [class] As String = typeName.ToString.Substring(typeName.ToString.LastIndexOf(".") + 1) 'create an instance of the object of typeName by its class alone Dim instance As Object = CreateInstance(typeName.GetType, [class], New Object() {}) 'get the type of the object Dim invoker As Type = instance.GetType Dim result As Object result = invoker.InvokeMember(methodName, Reflection.BindingFlags.Public Or Reflection.BindingFlags.Instance Or Reflection.BindingFlags.InvokeMethod, Nothing, instance, param) Return CType(result, T) End FunctionThe CreateInstance method was a code copy from another site, go here
Nothing but something- Marked As Answer by goldbishop Wednesday, March 10, 2010 5:42 PM

