Forum Discussion

carbon's avatar
carbon
New Contributor II
2 days ago

Extract args properties


Hi, is there a way to copy the list of all functions displayed after args.cubeview.?



 

1 Reply

  • RobbSalzmann's avatar
    RobbSalzmann
    Valued Contributor II

    Not sure what you are asking for, in the title you say properties, then in the body of your post you want functions(assuming methods).  The examples below provide either.

    Here is an example that uses the Reflection API to parse properties and their values, GetAllPropertyNamesAndValues and parse the names of the public Methods, GetAllMethodNamesAsList on the args.CubeView object passed into Main on a CubeViewExtender:

    Imports System
    Imports System.Collections.Generic
    Imports System.Data
    Imports System.Data.Common
    Imports System.Globalization
    Imports System.IO
    Imports System.Reflection
    Imports System.Linq
    Imports Microsoft.VisualBasic
    Imports OneStream.Finance.Database
    Imports OneStream.Finance.Engine
    Imports OneStream.Shared.Common
    Imports OneStream.Shared.Database
    Imports OneStream.Shared.Engine
    Imports OneStream.Shared.Wcf
    Imports OneStream.Stage.Database
    Imports OneStream.Stage.Engine
    Imports Newtonsoft.Json
    
    Namespace OneStream.BusinessRule.CubeViewExtender.IntrospectionReflector
    	Public Class MainClass
    		Public Function Main(ByVal si As SessionInfo, ByVal globals As BRGlobals, ByVal api As Object, ByVal args As CVExtenderArgs) As Object
    			Try
    				'Reflect the methods of args.CubeView
    				Dim ArgsCubeViewFunctions As List(Of String) = GetAllMethodNamesAsList(args.CubeView)
    				BRApi.ErrorLog.LogMessage(si, JsonConvert.SerializeObject(ArgsCubeViewFunctions, Formatting.Indented))
    				
    				Dim ArgsCubeViewProperties As Dictionary(Of String, Object) = GetAllPropertyNamesAndValues(args.CubeView)
    				BRApi.ErrorLog.LogMessage(si, JsonConvert.SerializeObject(ArgsCubeViewProperties, Formatting.Indented))
    
    				Return Nothing
    			Catch ex As Exception
    				Throw ErrorHandler.LogWrite(si, New XFException(si, ex))
    			End Try
    		End Function
    		
            ''' <summary>
            ''' Return all instance method names defined on the provided cubeView object.
            ''' Filters out compiler "special name" methods (for example, property getters and setters).
            ''' </summary>
            ''' <param name="cubeView">The args.CubeView object to inspect.</param>
            ''' <param name="includeNonPublic">Set True to include Friend/Private instance methods.</param>
            Public Function GetAllMethodNamesAsList(cubeView As Object,
                                                           Optional includeNonPublic As Boolean = False) As List(Of String)
                If cubeView Is Nothing Then
                    Throw New ArgumentNullException(NameOf(cubeView), "cubeView cannot be null.")
                End If
    
                Dim flags As BindingFlags = BindingFlags.Instance Or BindingFlags.Public
                If includeNonPublic Then
                    flags = flags Or BindingFlags.NonPublic
                End If
    
                Dim typeInfo As Type = cubeView.GetType()
    
                Dim methodNames As List(Of String) =
                    typeInfo.
                        GetMethods(flags).
                        Where(Function(m) Not m.IsSpecialName).               ' Exclude get_Foo/set_Foo, add_Event, op_*, etc.
                        Select(Function(m) m.Name).
                        Distinct(StringComparer.Ordinal).
                        OrderBy(Function(n) n, StringComparer.Ordinal).
                        ToList()
    
                Return methodNames
            End Function
    		
    		 ''' <summary>
            ''' Return all readable, non-indexed instance property names and their current values
            ''' for the provided cubeView object. If a property getter throws, the dictionary value
            ''' contains a descriptive error string rather than raising an exception.
            ''' </summary>
            ''' <param name="cubeView">The args.CubeView object to inspect.</param>
            ''' <param name="includeNonPublic">Set True to include Friend/Private instance properties.</param>
            Public Function GetAllPropertyNamesAndValues(cubeView As Object,
                                                                Optional includeNonPublic As Boolean = False) As Dictionary(Of String, Object)
                If cubeView Is Nothing Then
                    Throw New ArgumentNullException(NameOf(cubeView), "cubeView cannot be null.")
                End If
    
                Dim flags As BindingFlags = BindingFlags.Instance Or BindingFlags.Public
                If includeNonPublic Then
                    flags = flags Or BindingFlags.NonPublic
                End If
    
                Dim typeInfo As Type = cubeView.GetType()
                Dim result As New Dictionary(Of String, Object)(StringComparer.Ordinal)
    
                For Each propertyInfo As PropertyInfo In typeInfo.GetProperties(flags)
                    ' Skip write-only or indexer properties (those that require parameters).
                    If Not propertyInfo.CanRead Then
                        Continue For
                    End If
                    If propertyInfo.GetIndexParameters().Length > 0 Then
                        Continue For
                    End If
    
                    Dim value As Object = Nothing
                    Try
                        value = propertyInfo.GetValue(cubeView, Nothing)
                    Catch ex As TargetInvocationException
                        Dim root As Exception = If(ex.InnerException, ex)
                        value = String.Format($"<Error retrieving value: {root.GetType().Name}: {root.Message}>")
                    Catch ex As Exception
                        value = String.Format($"<Error retrieving value: {ex.GetType().Name}: {ex.Message}>")
                    End Try
    
                    result(propertyInfo.Name) = value
                Next
    
                ' Sort into a new dictionary for deterministic ordering when enumerated.
                Dim ordered As New Dictionary(Of String, Object)(
                    result.OrderBy(Function(kv) kv.Key, StringComparer.Ordinal).
                           ToDictionary(Function(kv) kv.Key, Function(kv) kv.Value),
                    StringComparer.Ordinal)
    
                Return ordered
            End Function
    	End Class
    End Namespace