locked
VB.Net Reflection Method Invoke returns null RRS feed

  • Question

  • User-1962621908 posted

    I need to access few private methods and members in the Microsoft.VisualStudio.Data.Tools.Package.dll . I did the following coding. everything works fine until the last code line.

    Dim dte As EnvDTE.DTE
    Dim configuration As EnvDTE.Configuration
    Dim projectConfigProperties As Microsoft.VisualStudio.Data.Tools.Package.Project.Internal.ProjectConfigProperties
    
    ' Get the Assembly info 
    Dim name As AssemblyName = New AssemblyName()
    name.CodeBase = "file://C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\Microsoft\SQLDB\Microsoft.VisualStudio.Data.Tools.Package.dll"
    Dim dbProjectType As Type = assembly.GetType("Microsoft.VisualStudio.Data.Tools.Package.Project.DatabaseProjectPropertyValueType", True, True)
    ' Retrieve the enum info from the assembly 
    Dim fields As FieldInfo() = dbProjectType.GetFields((BindingFlags.Public Or BindingFlags.Static Or BindingFlags.NonPublic))
    
    Dim databaseProjectConfig As Microsoft.VisualStudio.Data.Tools.Package.Project.DatabaseProjectConfig
    configuration = project.ConfigurationManager.ActiveConfiguration
    projectConfigProperties = CType(configuration.Object, Microsoft.VisualStudio.Data.Tools.Package.Project.Internal.ProjectConfigProperties)
    projectConfigObject = projectConfigProperties.GetType().GetProperty("ProjectConfig", System.Reflection.BindingFlags.NonPublic Or System.Reflection.BindingFlags.Instance).GetValue(projectConfigProperties)
    databaseProjectConfig = CType(projectConfigObject, Microsoft.VisualStudio.Data.Tools.Package.Project.DatabaseProjectConfig)
    
    Dim types As Type() = New Type() {GetType(String), GetType(Boolean), dbProjectType}
    ' Get method info 
    Dim myMethod As MethodInfo = databaseProjectConfig.GetType().GetMethod("GetConfigurationProperty", BindingFlags.NonPublic Or BindingFlags.Instance, Nothing, types, Nothing)
    ' Invoke the method 
    Dim val = myMethod.Invoke(projectConfigObject, New Object() {"SqlCommandVariablesFile", False, fields(0).GetValue(Nothing)})

    The myMethod populates correctly. But when I try to invoke it, the val is always getting a null value. It would be great if someone can tell me where I went wrong.

    Thursday, January 5, 2017 3:56 AM

Answers

  • User-1962621908 posted

    Hi,

     I found the route cause in this problem when we are Invoking a method through reflection, we need to pass-in the exact matching param types in the Invoke method. That is why it was returned as null. After I passed in the exact same param types the method returned successfully. 

    Following is the code I used and it worked. 

    Setting up the type properties.

    Dim fields As FieldInfo() = dbProjectType.GetFields((BindingFlags.Public Or BindingFlags.Static Or BindingFlags.NonPublic))
    
     '' Get Internal enum DatabaseProjectEventPropagation using reflection 
    Dim dbeventPropagationType As Type = assembly.GetType("Microsoft.VisualStudio.Data.Tools.Package.Project.DatabaseProjectEventPropagation", True, True)
    Dim dbEventPropgationFields As FieldInfo() = dbeventPropagationType.GetFields((BindingFlags.Public Or BindingFlags.Static Or BindingFlags.NonPublic))
    
    Dim readTypes As Type() = New Type() {GetType(String), GetType(Boolean), dbProjectType}
     Dim writeTypes As Type() = New Type() {GetType(String), GetType(String), dbeventPropagationType, GetType(Microsoft.VisualStudio.Shell.Interop._PersistStorageType)}

    Define the methods that we need to access via reflection 

    projectConfigProperties = CType(configuration.Object, Microsoft.VisualStudio.Data.Tools.Package.Project.Internal.ProjectConfigProperties)
    projectConfigObject = projectConfigProperties.GetType().GetProperty("ProjectConfig", System.Reflection.BindingFlags.NonPublic Or System.Reflection.BindingFlags.Instance).GetValue(projectConfigProperties)
    databaseProjectConfig = CType(projectConfigObject, Microsoft.VisualStudio.Data.Tools.Package.Project.DatabaseProjectConfig)
    
    Dim getPropertyMethod As MethodInfo = databaseProjectConfig.GetType().GetMethod("GetConfigurationProperty", BindingFlags.NonPublic Or BindingFlags.Instance, Nothing, readTypes, Nothing)
    Dim setPropertyMethod As MethodInfo = databaseProjectConfig.GetType().GetMethod("SetConfigurationProperty", BindingFlags.NonPublic Or BindingFlags.Instance, Nothing, writeTypes, Nothing)

    Invoking methods 

    Dim val = getPropertyMethod.Invoke(projectConfigObject, New Object() {"AnsiNulls", False, fields(0).GetValue(Nothing)})
    setPropertyMethod.Invoke(projectConfigObject, New Object() {"AnsiNulls", "False", dbEventPropgationFields(0).GetValue(Nothing), Microsoft.VisualStudio.Shell.Interop._PersistStorageType.PST_PROJECT_FILE})

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, January 16, 2017 10:07 PM

All replies

  • User-271186128 posted

    Hi priyalwalpita,

    projectConfigObject = projectConfigProperties.GetType().GetProperty("ProjectConfig", System.Reflection.BindingFlags.NonPublic Or System.Reflection.BindingFlags.Instance).GetValue(projectConfigProperties)
    
    
    Dim val = myMethod.Invoke(projectConfigObject, New Object() {"SqlCommandVariablesFile", False, fields(0).GetValue(Nothing)})

    According to your code, it seems that you are invoke the property, instead of the methods. Please set a break point to check whether you set value for this property.

    More details about using reflection, please refer to the following code:

    Imports System
    Imports System.Reflection
    
    Public Class MagicClass
        Private magicBaseValue As Integer
    
        Public Sub New()
            magicBaseValue = 9
        End Sub
    
        Public Function ItsMagic(preMagic As Integer) As Integer
            Return preMagic * magicBaseValue
        End Function
    End Class
    
    Public Class TestMethodInfo
        Public Shared Sub Main()
            ' Get the constructor and create an instance of MagicClass
    
            Dim magicType As Type = Type.GetType("MagicClass")
            Dim magicConstructor As ConstructorInfo = magicType.GetConstructor(Type.EmptyTypes)
            Dim magicClassObject As Object = magicConstructor.Invoke(New Object(){})
    
            ' Get the ItsMagic method and invoke with a parameter value of 100
    
            Dim magicMethod As MethodInfo = magicType.GetMethod("ItsMagic")
            Dim magicValue As Object = magicMethod.Invoke(magicClassObject, New Object(){100})
    
            Console.WriteLine("MethodInfo.Invoke() Example" + vbNewLine)
            Console.WriteLine("MagicClass.ItsMagic() returned: {0}", magicValue)
        End Sub
    End Class
    

    When invoke the method, you could also set a break point in the method to check the return data.

    More details, see: https://msdn.microsoft.com/en-us/library/a89hcwhh(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2

    Best regards,
    Dillion

    Friday, January 6, 2017 10:04 AM
  • User-1962621908 posted

    Hi,

     I found the route cause in this problem when we are Invoking a method through reflection, we need to pass-in the exact matching param types in the Invoke method. That is why it was returned as null. After I passed in the exact same param types the method returned successfully. 

    Following is the code I used and it worked. 

    Setting up the type properties.

    Dim fields As FieldInfo() = dbProjectType.GetFields((BindingFlags.Public Or BindingFlags.Static Or BindingFlags.NonPublic))
    
     '' Get Internal enum DatabaseProjectEventPropagation using reflection 
    Dim dbeventPropagationType As Type = assembly.GetType("Microsoft.VisualStudio.Data.Tools.Package.Project.DatabaseProjectEventPropagation", True, True)
    Dim dbEventPropgationFields As FieldInfo() = dbeventPropagationType.GetFields((BindingFlags.Public Or BindingFlags.Static Or BindingFlags.NonPublic))
    
    Dim readTypes As Type() = New Type() {GetType(String), GetType(Boolean), dbProjectType}
     Dim writeTypes As Type() = New Type() {GetType(String), GetType(String), dbeventPropagationType, GetType(Microsoft.VisualStudio.Shell.Interop._PersistStorageType)}

    Define the methods that we need to access via reflection 

    projectConfigProperties = CType(configuration.Object, Microsoft.VisualStudio.Data.Tools.Package.Project.Internal.ProjectConfigProperties)
    projectConfigObject = projectConfigProperties.GetType().GetProperty("ProjectConfig", System.Reflection.BindingFlags.NonPublic Or System.Reflection.BindingFlags.Instance).GetValue(projectConfigProperties)
    databaseProjectConfig = CType(projectConfigObject, Microsoft.VisualStudio.Data.Tools.Package.Project.DatabaseProjectConfig)
    
    Dim getPropertyMethod As MethodInfo = databaseProjectConfig.GetType().GetMethod("GetConfigurationProperty", BindingFlags.NonPublic Or BindingFlags.Instance, Nothing, readTypes, Nothing)
    Dim setPropertyMethod As MethodInfo = databaseProjectConfig.GetType().GetMethod("SetConfigurationProperty", BindingFlags.NonPublic Or BindingFlags.Instance, Nothing, writeTypes, Nothing)

    Invoking methods 

    Dim val = getPropertyMethod.Invoke(projectConfigObject, New Object() {"AnsiNulls", False, fields(0).GetValue(Nothing)})
    setPropertyMethod.Invoke(projectConfigObject, New Object() {"AnsiNulls", "False", dbEventPropgationFields(0).GetValue(Nothing), Microsoft.VisualStudio.Shell.Interop._PersistStorageType.PST_PROJECT_FILE})

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, January 16, 2017 10:07 PM