membercache.vb
来自「大名鼎鼎的mono是.NET平台的跨平台(支持linux」· VB 代码 · 共 347 行
VB
347 行
' ' Visual Basic.Net Compiler' Copyright (C) 2004 - 2007 Rolf Bjarne Kvinge (RKvinge@novell.com)' ' This library is free software; you can redistribute it and/or' modify it under the terms of the GNU Lesser General Public' License as published by the Free Software Foundation; either' version 2.1 of the License, or (at your option) any later version.' ' This library is distributed in the hope that it will be useful,' but WITHOUT ANY WARRANTY; without even the implied warranty of' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU' Lesser General Public License for more details.' ' You should have received a copy of the GNU Lesser General Public' License along with this library; if not, write to the Free Software' Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA' Imports System.Collections.GenericPublic Class MemberCache Private m_Compiler As Compiler Private m_Cache As New MemberCacheEntries Private m_CacheInsensitive As MemberCacheEntries Private m_FlattenedCache As MemberCacheEntries Private m_FlattenedCacheInsensitive As MemberCacheEntries Private m_Type As Type Private m_Base As MemberCache Sub New(ByVal Compiler As Compiler, ByVal Type As Type) m_Compiler = Compiler m_Type = Type Load() Flatten() Compiler.TypeManager.MemberCache.Add(Type, Me) End Sub ReadOnly Property Compiler() As Compiler Get Return m_Compiler End Get End Property ReadOnly Property Cache() As MemberCacheEntries Get Return m_Cache End Get End Property ReadOnly Property FlattenedCache() As MemberCacheEntries Get Return m_FlattenedCache End Get End Property Sub Load() Dim members() As MemberInfo Log("Caching type: " & m_Type.Name) 'If m_Type.Name = "ParameterList" Then Helper.StopIfDebugging() members = m_Type.GetMembers(BindingFlags.Instance Or BindingFlags.Static Or BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.DeclaredOnly) For Each member As MemberInfo In members If m_Cache.ContainsKey(member.Name) = False Then m_Cache.Add(New MemberCacheEntry(member)) Else m_Cache(member.Name).Members.Add(member) End If Next End Sub Sub Flatten() Dim base As MemberCache base = GetBaseCache() If base Is Nothing Then If m_Type.IsInterface AndAlso m_Type.IsGenericParameter = False Then Dim ifaces() As Type Dim icache As MemberCache ifaces = m_Type.GetInterfaces() For Each iface As Type In ifaces icache = m_Compiler.TypeManager.GetCache(iface) FlattenWith(icache) Next FlattenWith(m_Compiler.TypeManager.GetCache(Compiler.TypeCache.System_Object)) Else m_FlattenedCache = m_Cache End If Return End If If base.FlattenedCache Is Nothing Then m_FlattenedCache = m_Cache Return End If FlattenWith(base) End Sub Private Sub FlattenWith(ByVal MemberCache As MemberCache) If m_FlattenedCache Is Nothing Then m_FlattenedCache = New MemberCacheEntries(m_Cache) End If For Each cache As MemberCacheEntry In MemberCache.FlattenedCache.Values For i As Integer = 0 To cache.Members.Count - 1 Dim member As MemberInfo = cache.Members(i) If Not IsHidden(member) Then If m_FlattenedCache.ContainsKey(cache.Name) = False Then m_FlattenedCache.Add(New MemberCacheEntry(member)) ElseIf m_FlattenedCache(cache.Name).Members.Contains(member) = False Then m_FlattenedCache(cache.Name).Members.Add(member) End If End If Next Next End Sub Private Sub Log(ByVal Msg As String) 'Compiler.Report.WriteLine(Msg) End Sub Private Sub LogExtended(ByVal Msg As String) Return Compiler.Report.WriteLine(Msg) End Sub Function IsHidden(ByVal baseMember As MemberInfo) As Boolean Dim current As MemberCacheEntry Dim memberParameterTypes As Type() = Nothing current = Lookup(baseMember.Name) If current Is Nothing Then#If DEBUG Then LogExtended("MemberCache.IsHidden (false, no current match), type=" & m_Type.Name & ", name=" & baseMember.Name)#End If Return False End If For i As Integer = 0 To current.Members.Count - 1 Dim thisMember As MemberInfo = current.Members(i) If thisMember.MemberType <> baseMember.MemberType Then#If DEBUG Then LogExtended("MemberCache.IsHidden (true, different member types), type=" & m_Type.Name & ", name=" & thisMember.Name)#End If Return True End If Select Case thisMember.MemberType Case MemberTypes.Constructor, MemberTypes.Event, MemberTypes.Field, MemberTypes.NestedType, MemberTypes.TypeInfo#If DEBUG Then LogExtended("MemberCache.IsHidden (true, non overloadable member type), type=" & m_Type.Name & ", name=" & thisMember.Name)#End If Return True Case MemberTypes.Property, MemberTypes.Method Dim methodAttributes As MethodAttributes Dim isHideBySig, isVirtual, isNewSlot As Boolean Dim isOverrides As Boolean methodAttributes = Helper.GetMethodAttributes(thisMember) isHideBySig = CBool(methodAttributes And Reflection.MethodAttributes.HideBySig) isVirtual = CBool(methodAttributes And Reflection.MethodAttributes.Virtual) isNewSlot = CBool(methodAttributes And Reflection.MethodAttributes.NewSlot) isOverrides = isVirtual AndAlso isNewSlot = False If isHideBySig = False AndAlso isOverrides = False Then#If DEBUG Then LogExtended("MemberCache.IsHidden (true, shadowed member), type=" & m_Type.Name & ", name=" & thisMember.Name)#End If Return True End If If memberParameterTypes Is Nothing Then memberParameterTypes = Helper.GetTypes(Helper.GetParameters(m_Compiler, baseMember)) If Helper.CompareTypes(Helper.GetTypes(Helper.GetParameters(m_Compiler, thisMember)), memberParameterTypes) Then#If DEBUG Then LogExtended("MemberCache.IsHidden (true, exact signature), type=" & m_Type.Name & ", name=" & thisMember.Name)#End If Return True End If Case Else Throw New InternalException("") End Select Next#If DEBUG Then LogExtended("MemberCache.IsHidden (false, no match at all), type=" & m_Type.Name & ", name=" & baseMember.Name)#End If Return False End Function Function GetBaseCache() As MemberCache If m_Base IsNot Nothing Then Return m_Base Dim base As Type base = m_Type.BaseType If base Is Nothing Then Return Nothing If m_Compiler.TypeManager.MemberCache.ContainsKey(base) = False Then m_Base = New MemberCache(m_Compiler, base) Else m_Base = m_Compiler.TypeManager.MemberCache(base) End If Return m_Base End Function ''' <summary> ''' Looks up the name in the flattened cache. ''' Looks case-insensitively ''' </summary> ''' <param name="Name"></param> ''' <returns></returns> ''' <remarks></remarks> Function LookupFlattened(ByVal Name As String) As MemberCacheEntry If m_FlattenedCacheInsensitive Is Nothing Then m_FlattenedCacheInsensitive = New MemberCacheEntries(m_FlattenedCache.Count, NameResolution.StringComparer) For Each item As KeyValuePair(Of String, MemberCacheEntry) In m_FlattenedCache Dim current As MemberCacheEntry = Nothing If m_FlattenedCacheInsensitive.TryGetValue(item.Key, current) = False Then current = New MemberCacheEntry(item.Key) m_FlattenedCacheInsensitive.Add(current) End If current.Members.AddRange(item.Value.Members) Next End If If m_FlattenedCacheInsensitive.ContainsKey(Name) Then Return m_FlattenedCacheInsensitive(Name) Else Return Nothing End If End Function Sub ResetFlattenedCacheInsensitive() m_FlattenedCacheInsensitive = Nothing End Sub ''' <summary> ''' This function returns the members list in the cache, or nothing ''' </summary> ''' <param name="Name"></param> ''' <returns></returns> ''' <remarks></remarks> Function LookupFlattenedMembers(ByVal Name As String) As Generic.List(Of MemberInfo) Dim cache As MemberCacheEntry = LookupFlattened(Name) If cache Is Nothing Then Return Nothing Return cache.Members End Function ''' <summary> ''' This function returns a COPY of the members list in the cache. ''' To be avoided if possible. ''' </summary> ''' <param name="Name"></param> ''' <returns></returns> ''' <remarks></remarks> Function LookupMembersFlattened(ByVal Name As String) As Generic.List(Of MemberInfo) Dim result As New Generic.List(Of MemberInfo) Dim tmp As MemberCacheEntry tmp = LookupFlattened(Name) If tmp IsNot Nothing Then result.AddRange(tmp.members) End If Return result End Function ''' <summary> ''' Looks up the name in the cache. ''' Looks case-insensitively ''' </summary> ''' <param name="Name"></param> ''' <returns></returns> ''' <remarks></remarks> Function Lookup(ByVal Name As String) As MemberCacheEntry If m_CacheInsensitive Is Nothing Then m_CacheInsensitive = New MemberCacheEntries(NameResolution.StringComparer) For Each item As KeyValuePair(Of String, MemberCacheEntry) In m_Cache Dim current As MemberCacheEntry If m_CacheInsensitive.ContainsKey(item.Key) = False Then current = New MemberCacheEntry(item.Key) m_CacheInsensitive.Add(current) Else current = m_CacheInsensitive(item.Key) End If current.Members.AddRange(item.Value.Members) Next End If If m_CacheInsensitive.ContainsKey(Name) Then Return m_CacheInsensitive(Name) Else Return Nothing End If End FunctionEnd ClassPublic Class MemberCacheEntries Inherits Generic.Dictionary(Of String, MemberCacheEntry) Shadows Sub Add(ByVal Entry As MemberCacheEntry) MyBase.Add(Entry.Name, Entry) End Sub Sub New() End Sub Sub New(ByVal compare As IEqualityComparer(Of String)) MyBase.New(compare) End Sub Sub New(ByVal Capacity As Integer, ByVal compare As IEqualityComparer(Of String)) MyBase.New(Capacity, compare) End Sub Sub New(ByVal Dictionary As MemberCacheEntries) MyBase.New(Dictionary) End Sub Function GetAllMembers() As Generic.List(Of MemberInfo) Dim result As New Generic.List(Of MemberInfo) For Each item As MemberCacheEntry In Me.Values result.AddRange(item.Members) Next Return result End FunctionEnd ClassPublic Class MemberCacheEntry Public Name As String Public Members As New Generic.List(Of MemberInfo) Sub New(ByVal Name As String) Me.Name = Name End Sub Sub New(ByVal Name As String, ByVal ParamArray Members As MemberInfo()) Me.Name = Name Me.Members.AddRange(Members) End Sub Sub New(ByVal Member As MemberInfo) Me.Name = Member.Name Me.Members.Add(Member) End SubEnd Class
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?