Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
Data Viewer - AssemblyScanner.vb

AssemblyScanner.vb

Caricato da: Totem
Scarica il programma completo

  1. Imports System.Reflection
  2. Imports System.Text
  3. Module AssemblyScanner
  4.  
  5.     'Questa classe è presa da quella che ho scritto per la guida
  6.     'http://totem.altervista.org/guida/versione2/index.php
  7.  
  8.     'Funzione privata che restituisce lo specificatore di accesso di
  9.     'un membro.
  10.     'Questa funzione utilizza un meccanismo di late-binding per
  11.     'risparmiare spazio, seguendo il seguente ragionamento: non si puo'
  12.     'specificare come parametro un oggetto di tipo MemberInfo, poiche'
  13.     'questo non espone le proprita' che servono alla funzione; scrivere un
  14.     'overload di funzioni sprecherebbe troppo spazio; la conclusione
  15.     'logica piu' semplice e' quella di usare un parametro di tipo Object, che
  16.     'poiche' la funzione e' privata, sara' sempre dotato di tali proprieta'
  17.     'in quanto saremo noi stessi a passare parametri adeguati
  18.     Private Function GetScope(ByVal MI As Object) As String
  19.         Dim Scope As String
  20.         If MI.IsAssembly Then
  21.             Scope = "Friend"
  22.         ElseIf MI.IsFamily Then
  23.             Scope = "Protected"
  24.         ElseIf MI.IsFamilyOrAssembly Then
  25.             Scope = "Protected Friend"
  26.         ElseIf MI.IsPrivate Then
  27.             Scope = "Private"
  28.         ElseIf MI.IsPublic Then
  29.             Scope = "Public"
  30.         End If
  31.         Return Scope
  32.     End Function
  33.  
  34.     'Determina se il membro ha un nome speciale. Ad esempio, si e' visto
  35.     'che la reflection considera Get e Set di una proprieta' come metodi
  36.     'a se' stanti. Percio' se c'e' una proprieta' A in una classe,
  37.     'la reflection enumerera' anche i metodi get_A e set_A, che corrispondono
  38.     'ai blocchi Get e Set. Per evitare questo, e altri problemi simili,
  39.     'si deve controllare che IsSpecialName sia false.
  40.     Private Function IsSpecialName(ByVal Member As Object) As Boolean
  41.         Return Member.IsSpecialName
  42.     End Function
  43.  
  44.     'Funzione privata che restituisce il nome di un tipo. Utilizza una
  45.     'algoritmo ricorsivo, poiche' potrebbero anche esserci generic nidificati,
  46.     'come ad esempio:
  47.     'Dim A As New List(Of Dictionary(Of String, Of Nullable(Of Integer)))
  48.     'Non si sa mai...
  49.     Public Function GetTypeName(ByVal T As Type) As String
  50.         Dim CompleteName As New StringBuilder
  51.  
  52.         If T.IsGenericType And T.Name.IndexOf("`") >= 0 Then
  53.             Dim Position As Int16 = 0
  54.             CompleteName.Append(T.Name.Remove(T.Name.IndexOf("`")))
  55.             CompleteName.Append("(Of ")
  56.             For Each GenArg As Type In T.GetGenericArguments
  57.                 If Position > 0 Then
  58.                     CompleteName.Append(", ")
  59.                 End If
  60.                 'Qui la funzione richiama se' stessa
  61.                 CompleteName.Append(GetTypeName(GenArg))
  62.             Next
  63.             CompleteName.Append(")")
  64.         Else
  65.             CompleteName.Append(T.Name)
  66.         End If
  67.  
  68.         Return CompleteName.ToString
  69.     End Function
  70.  
  71.     Public Function GetTypeRelatedTypes(ByVal T As Type) As List(Of Type)
  72.         Dim Result As New List(Of Type)
  73.  
  74.         If T.IsGenericType And T.Name.IndexOf("`") >= 0 Then
  75.             For Each GenArg As Type In T.GetGenericArguments
  76.                 Result.Add(GenArg)
  77.             Next
  78.         Else
  79.             Result.Add(T)
  80.         End If
  81.  
  82.         Return Result
  83.     End Function
  84.  
  85.     'Analizza un tipo e ne restituisce il nome nella forma:
  86.     '[Scope] [Modifier] [Category] [Name]
  87.     'Ad esmpio:
  88.     'Public MustInherit Class Ciao
  89.     Public Function GetTypeInfo(ByVal T As Type) As String
  90.         Dim CompleteName As New StringBuilder
  91.  
  92.         'Non si puo' utilizzare la funzione GetScope poiche' le proprieta'
  93.         'di Type inerenti all'ambito di visibilita' hanno nome diverso
  94.         If T.IsNested Then
  95.             'Scope di tipi nidificati
  96.             If T.IsNestedAssembly Then
  97.                 CompleteName.Append("Friend ")
  98.             ElseIf T.IsNestedFamily Then
  99.                 CompleteName.Append("Protected ")
  100.             ElseIf T.IsNestedFamORAssem Then
  101.                 CompleteName.Append("Protected Friend ")
  102.             ElseIf T.IsNestedPrivate Then
  103.                 CompleteName.Append("Private ")
  104.             ElseIf T.IsNestedPublic Then
  105.                 CompleteName.Append("Public ")
  106.             End If
  107.         Else
  108.             'Scope di tipi non nidificati
  109.             If T.IsPublic Then
  110.                 CompleteName.Append("Public ")
  111.             ElseIf T.IsNotPublic Then
  112.                 'Dato che per i tipi non nidificati non si puo' sapere
  113.                 'con precisione lo scope, se non sono pubblici si mette
  114.                 'un generico NotPublic. Questa non e' una keyword del Vb.Net
  115.                 CompleteName.Append("NotPublic ")
  116.             End If
  117.         End If
  118.  
  119.         'Modificatori vari di ereditarieta' (valgono solo per le classi)
  120.         If T.IsClass Then
  121.             If T.IsAbstract Then
  122.                 CompleteName.Append("MustInherit ")
  123.             ElseIf T.IsSealed Then
  124.                 CompleteName.Append("NotInheritable ")
  125.             End If
  126.         End If
  127.  
  128.         'Categoria del tipo
  129.         If T.IsClass Then
  130.             CompleteName.Append("Class ")
  131.         ElseIf T.IsEnum Then
  132.             CompleteName.Append("Enum ")
  133.         ElseIf T.IsInterface Then
  134.             CompleteName.Append("Interface ")
  135.         ElseIf T.IsValueType Then
  136.             'Dato che Type rappresenta un tipo, solo le struttura sono
  137.             'comprese nei tipi Value, poiche' non e' possibile definire
  138.             'tipi base come Char e String
  139.             CompleteName.Append("Structure ")
  140.         End If
  141.  
  142.         CompleteName.Append(T.Name)
  143.  
  144.         'Se e' una dichiarazione di un tipo generic, bisogna ricordarsi
  145.         'di aggiunge la signature degli argomenti generic.
  146.         'Attenzione! Type.IsGenericType e Type.IsGenericTypeDefinition
  147.         'sono proprieta' diverse! La prima specifica un tipo generic collegato
  148.         'mentre la seconda una definizione di tipo generic. Ad esempio:
  149.         '"Class Ciao(Of T1, T2)" oppure "Sub Ciao(Of K1, K2)"
  150.         'Sono definizioni di tipi generic, mentre
  151.         '"Dim A As List(Of Integer)" e "..., ByVal Elem1 As K1"
  152.         'Sono tipi generic collegati
  153.         If T.IsGenericTypeDefinition Then
  154.             Dim Position As Int16 = 0
  155.             CompleteName.Append("(Of ")
  156.             For Each GenArg As Type In T.GetGenericArguments
  157.                 If Position > 0 Then
  158.                     CompleteName.Append(", ")
  159.                 End If
  160.                 CompleteName.Append(GenArg.Name)
  161.                 Position += 1
  162.             Next
  163.             CompleteName.Append(")")
  164.         End If
  165.  
  166.         Return CompleteName.ToString
  167.     End Function
  168.  
  169.     'Analizza un metodo e ne restituisce il nome nella forma:
  170.     '[Scope] (Shared) [Modifier] [Category] [Name][Signature]
  171.     'Ad esempio:
  172.     'Protected Overridable Sub Ciao(Of T)(ByVal A As List(Of T))
  173.     Public Function GetMethodInfo(ByVal MI As MethodInfo) As String
  174.         Dim CompleteName As New StringBuilder
  175.  
  176.         'MethodInfo espone tutte le proprieta' necessarie, quindi e'
  177.         'lecito passarlo come parametro a GetScope
  178.         CompleteName.Append("  " & GetScope(MI) & " ")
  179.  
  180.         'Se e' shared oppure no
  181.         If MI.IsStatic Then
  182.             CompleteName.Append("Shared ")
  183.         End If
  184.  
  185.         'Modificatori
  186.         If MI.IsAbstract Then
  187.             CompleteName.Append("MustOverride ")
  188.         ElseIf MI.IsFinal Then
  189.             'Niente
  190.         ElseIf MI.IsVirtual Then
  191.             CompleteName.Append("Overridable ")
  192.         End If
  193.  
  194.         'Categoria
  195.         If MI.ReturnType IsNot GetType(Void) Then
  196.             CompleteName.Append("Function ")
  197.         Else
  198.             CompleteName.Append("Sub ")
  199.         End If
  200.  
  201.         'Se e'un costruttore oppure no
  202.         If MI.IsConstructor Then
  203.             CompleteName.Append("New")
  204.         Else
  205.             CompleteName.Append(MI.Name)
  206.         End If
  207.  
  208.         'Signature
  209.         Dim Position As Int16 = 0
  210.  
  211.         'Potrebbe essere un metodo generic
  212.         If MI.IsGenericMethodDefinition Then
  213.             CompleteName.Append("(Of ")
  214.             For Each GenArg As Type In MI.GetGenericArguments
  215.                 If Position > 0 Then
  216.                     CompleteName.Append(", ")
  217.                 End If
  218.                 CompleteName.Append(GenArg.Name)
  219.                 Position += 1
  220.             Next
  221.             CompleteName.Append(")")
  222.             Position = 0
  223.         End If
  224.  
  225.         CompleteName.Append("(")
  226.         For Each ArgTy As ParameterInfo In MI.GetParameters
  227.             If Position > 0 Then
  228.                 CompleteName.Append(", ")
  229.             End If
  230.             If ArgTy.ParameterType.IsByRef Then
  231.                 CompleteName.Append("ByRef ")
  232.             Else
  233.                 CompleteName.Append("ByVal ")
  234.             End If
  235.             If ArgTy.IsOptional Then
  236.                 CompleteName.Append("Optional ")
  237.             End If
  238.             CompleteName.Append(ArgTy.Name)
  239.             CompleteName.AppendFormat(" As {0}", GetTypeName(ArgTy.ParameterType))
  240.             If ArgTy.IsOptional Then
  241.                 CompleteName.AppendFormat(" = {0}", ArgTy.DefaultValue.ToString)
  242.             End If
  243.             Position += 1
  244.         Next
  245.         CompleteName.Append(")")
  246.  
  247.         If MI.ReturnType IsNot GetType(Void) Then
  248.             CompleteName.AppendFormat(" As {0}", GetTypeName(MI.ReturnType))
  249.         End If
  250.  
  251.         'Ora ci occupiamo del corpo
  252.         Dim MB As MethodBody = MI.GetMethodBody
  253.         Dim Desc As New StringBuilder
  254.  
  255.         If MB Is Nothing Then
  256.             Return CompleteName.ToString
  257.         End If
  258.  
  259.         'Massima memoria occupata sullo stack
  260.         Desc.AppendFormat("  Massima memoria stack : {0} bytes{1}", MB.MaxStackSize, vbCrLf)
  261.         Desc.AppendLine()
  262.  
  263.         If MB.LocalVariables.Count > 0 Then
  264.             'Variabili locali (LocalVariableInfo è una variante di FieldInfo)
  265.             Desc.AppendLine("Variabili locali:")
  266.             For Each L As LocalVariableInfo In MB.LocalVariables
  267.                 'Dato che non si può ottenere il nome, ci si deve
  268.                 'accontentare di un indice
  269.                 Desc.AppendFormat("  Var({0}) As {1}{2}", L.LocalIndex, L.LocalType.Name, vbCrLf)
  270.             Next
  271.             Desc.AppendLine()
  272.         End If
  273.  
  274.         If MB.ExceptionHandlingClauses.Count > 0 Then
  275.             'Gestione delle eccezioni
  276.             Desc.AppendLine("Gestori di eccezioni:")
  277.             For Each Ex As ExceptionHandlingClause In MB.ExceptionHandlingClauses
  278.                 'Tipo di clausola: distingue tra filtro (When),
  279.                 'clausola (Catch) o un blocco Finally
  280.                 Desc.AppendFormat("  Tipo : {0}{1}", Ex.Flags.ToString, vbCrLf)
  281.                 'Se si tratta di un blocco Catch, ne specifica la natura
  282.                 If Ex.Flags = ExceptionHandlingClauseOptions.Clause Then
  283.                     Desc.AppendLine("    Catch Ex As " & Ex.CatchType.Name & vbCrLf)
  284.                 End If
  285.                 'Offset, ossia posizione in bytes nel Try, del gestore
  286.                 Desc.AppendFormat("  Offset : {0}{1}", Ex.HandlerOffset, vbCrLf)
  287.                 'Lunghezza, in bytes, del codice eseguibile del gestore
  288.                 Desc.AppendFormat("  Lunghezza : {0}{1}", Ex.HandlerLength, vbCrLf)
  289.                 Desc.AppendLine()
  290.             Next
  291.         End If
  292.  
  293.         Return CompleteName.ToString & vbCrLf & Desc.ToString
  294.     End Function
  295.  
  296.     Public Function GetMethodRelatedTypes(ByVal MI As MethodInfo) As List(Of Type)
  297.         Dim Result As New List(Of Type)
  298.         Dim MB As MethodBody = MI.GetMethodBody
  299.  
  300.         'Parametri
  301.         For Each ArgTy As ParameterInfo In MI.GetParameters
  302.             Result.AddRange(GetTypeRelatedTypes(ArgTy.ParameterType))
  303.         Next
  304.  
  305.         'Tipo restituito
  306.         If MI.ReturnType IsNot GetType(Void) Then
  307.             Result.AddRange(GetTypeRelatedTypes(MI.ReturnType))
  308.         End If
  309.  
  310.         'Variabili Locali
  311.         If MB IsNot Nothing Then
  312.             For Each L As LocalVariableInfo In MB.LocalVariables
  313.                 Result.AddRange(GetTypeRelatedTypes(L.LocalType))
  314.             Next
  315.  
  316.             'Eccezioni
  317.             For Each Ex As ExceptionHandlingClause In MB.ExceptionHandlingClauses
  318.                 If Ex.Flags = ExceptionHandlingClauseOptions.Clause Then
  319.                     Result.AddRange(GetTypeRelatedTypes(Ex.CatchType))
  320.                 End If
  321.             Next
  322.         End If
  323.  
  324.         Return Result
  325.     End Function
  326.  
  327.     'Analizza un campo e ne restituisce il nome nella forma:
  328.     '(Const)/[Scope] [Modifier] [Nome] As [Tipo] (= [Costante])
  329.     Public Function GetFieldInfo(ByVal FI As FieldInfo) As String
  330.         Dim CompleteName As New StringBuilder
  331.  
  332.         CompleteName.Append(GetScope(FI) & " ")
  333.  
  334.         'Costante
  335.         If FI.IsLiteral Then
  336.             CompleteName.Append("Const ")
  337.         ElseIf FI.IsInitOnly Then
  338.             CompleteName.Append("ReadOnly ")
  339.         End If
  340.  
  341.         CompleteName.Append(FI.Name & " ")
  342.         CompleteName.AppendFormat("As {0}", GetTypeName(FI.FieldType))
  343.  
  344.         If FI.IsLiteral Then
  345.             CompleteName.AppendFormat(" = {0}", FI.GetRawConstantValue)
  346.         End If
  347.  
  348.         Return CompleteName.ToString
  349.     End Function
  350.  
  351.     Public Function GetFieldRelatedTypes(ByVal FI As FieldInfo) As List(Of Type)
  352.         Return GetTypeRelatedTypes(FI.FieldType)
  353.     End Function
  354.  
  355.     'Analizza una proprieta' e ne restituisce il nome:
  356.     '[Modifier] Property [Nome][Signature]
  357.     Public Function GetPropertyInfo(ByVal PI As PropertyInfo) As String
  358.         Dim CompleteName As New StringBuilder
  359.  
  360.         If PI.CanRead Then
  361.             If PI.CanWrite Then
  362.                 'Niente
  363.             Else
  364.                 CompleteName.Append("ReadOnly ")
  365.             End If
  366.         Else
  367.             CompleteName.Append("WriteOnly ")
  368.         End If
  369.  
  370.         CompleteName.Append("Property ")
  371.         CompleteName.Append(PI.Name)
  372.  
  373.         'Signature
  374.         Dim Position As Int16 = 0
  375.         CompleteName.Append("(")
  376.         For Each Arg As ParameterInfo In PI.GetIndexParameters
  377.             If Position > 0 Then
  378.                 CompleteName.Append(", ")
  379.             End If
  380.             CompleteName.Append("ByVal ")
  381.             If Arg.IsOptional Then
  382.                 CompleteName.Append("Optional ")
  383.             End If
  384.             CompleteName.Append(Arg.Name)
  385.             CompleteName.AppendFormat(" As {0}", GetTypeName(Arg.ParameterType))
  386.             If Arg.IsOptional Then
  387.                 CompleteName.AppendFormat(" = {0}", Arg.DefaultValue.ToString)
  388.             End If
  389.         Next
  390.         CompleteName.AppendFormat(") As {0}", GetTypeName(PI.PropertyType))
  391.  
  392.         Return CompleteName.ToString
  393.     End Function
  394.  
  395.     Public Function GetPropertyRelatedTypes(ByVal PI As PropertyInfo) As List(Of Type)
  396.         Dim Result As New List(Of Type)
  397.  
  398.         If PI.CanRead Then
  399.             Result.AddRange(GetMethodRelatedTypes(PI.GetGetMethod))
  400.         End If
  401.         If PI.CanWrite Then
  402.             Result.AddRange(GetMethodRelatedTypes(PI.GetSetMethod))
  403.         End If
  404.         Result.AddRange(GetTypeRelatedTypes(PI.PropertyType))
  405.         For Each Arg As ParameterInfo In PI.GetIndexParameters
  406.             Result.AddRange(GetTypeRelatedTypes(Arg.ParameterType))
  407.         Next
  408.  
  409.         Return Result
  410.     End Function
  411.  
  412.     'Analizza un evento e ne restituisce il nome nella forma:
  413.     'Event [Nome] As [Tipo]
  414.     Public Function GetEventInfo(ByVal EI As EventInfo) As String
  415.         Dim CompleteName As New StringBuilder
  416.  
  417.         CompleteName.AppendFormat("Event {0} As {1}", EI.Name, _
  418.         EI.EventHandlerType.Name)
  419.  
  420.         Return CompleteName.ToString
  421.     End Function
  422.  
  423.     Public Function GetEventRelatedTypes(ByVal EI As EventInfo) As List(Of Type)
  424.         Dim Result As New List(Of Type)
  425.  
  426.         Result.AddRange(GetTypeRelatedTypes(EI.EventHandlerType))
  427.  
  428.         Return Result
  429.     End Function
  430.  
  431.     Public Function GetMemberAttributes(ByVal Member As MemberInfo) As String
  432.         Dim Result As New StringBuilder
  433.         Dim Attr() As Object = Member.GetCustomAttributes(False)
  434.  
  435.         For I As Int16 = 0 To Attr.Length - 1
  436.             Result.AppendFormat("Attributo [{0}]: {1}{2}", I, GetTypeInfo(Attr(I).GetType), vbCrLf)
  437.             For Each PI As PropertyInfo In Attr(I).GetType.GetProperties
  438.                 If PI.CanRead AndAlso PI.GetGetMethod IsNot Nothing AndAlso PI.GetGetMethod.GetParameters.Length = 0 Then
  439.                     Result.AppendFormat("  {0} = {1}{2}", PI.Name, PI.GetValue(Attr(I), Nothing), vbCrLf)
  440.                 End If
  441.             Next
  442.         Next
  443.  
  444.         Return Result.ToString
  445.     End Function
  446.  
  447.     'Funzione che suddivide il membro in base al tipo
  448.     Public Function GetMemberInfo(ByVal Member As MemberInfo) As String
  449.         Dim Temp As String = ""
  450.  
  451.         If TypeOf Member Is MethodInfo Then
  452.             Temp = GetMethodInfo(Member)
  453.         ElseIf TypeOf Member Is FieldInfo Then
  454.             Temp = GetFieldInfo(Member)
  455.         ElseIf TypeOf Member Is PropertyInfo Then
  456.             Temp = GetPropertyInfo(Member)
  457.         ElseIf TypeOf Member Is EventInfo Then
  458.             Temp = GetEventInfo(Member)
  459.         ElseIf Member.MemberType = MemberTypes.NestedType Then
  460.             Temp = GetTypeInfo(Member)
  461.         End If
  462.  
  463.         Return Temp
  464.     End Function
  465.  
  466.     Public Function GetMemberRelatedTypes(ByVal Member As MemberInfo) As List(Of Type)
  467.         Dim Result As New List(Of Type)
  468.  
  469.         If TypeOf Member Is MethodInfo Then
  470.             Result.AddRange(GetMethodRelatedTypes(Member))
  471.         ElseIf TypeOf Member Is FieldInfo Then
  472.             Result.AddRange(GetFieldRelatedTypes(Member))
  473.         ElseIf TypeOf Member Is PropertyInfo Then
  474.             Result.AddRange(GetPropertyRelatedTypes(Member))
  475.         ElseIf TypeOf Member Is EventInfo Then
  476.             Result.AddRange(GetEventRelatedTypes(Member))
  477.         ElseIf Member.MemberType = MemberTypes.NestedType Then
  478.             Result.AddRange(GetTypeRelatedTypes(Member))
  479.         End If
  480.  
  481.         Return Result
  482.     End Function
  483. End Module