' 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., 59 Temple Place, Suite 330, Boston,
' MA 02111-1307, USA.
'
' Flee - Fast Lightweight Expression Evaluator
' Copyright © 2007 Eugene Ciloci
'
' Imports of static members into an expression
Imports System.Reflection
'''
Public NotInheritable Class ExpressionImports
Private Shared OurBuiltinTypeMap As Dictionary(Of String, Type) = CreateBuiltinTypeMap()
Private MyRootImport As NamespaceImport
Private MyOwnerImport As TypeImport
Private MyContext As ExpressionContext
Friend Sub New()
MyRootImport = New NamespaceImport(True)
End Sub
Private Shared Function CreateBuiltinTypeMap() As Dictionary(Of String, Type)
Dim map As New Dictionary(Of String, Type)(StringComparer.OrdinalIgnoreCase)
map.Add("boolean", GetType(Boolean))
map.Add("byte", GetType(Byte))
map.Add("sbyte", GetType(SByte))
map.Add("short", GetType(Short))
map.Add("ushort", GetType(UInt16))
map.Add("int", GetType(Int32))
map.Add("uint", GetType(UInt32))
map.Add("long", GetType(Long))
map.Add("ulong", GetType(ULong))
map.Add("single", GetType(Single))
map.Add("double", GetType(Double))
map.Add("decimal", GetType(Decimal))
map.Add("char", GetType(Char))
map.Add("object", GetType(Object))
map.Add("string", GetType(String))
Return map
End Function
#Region "Methods - Non public"
Friend Sub SetContext(ByVal context As ExpressionContext)
MyContext = context
MyRootImport.SetContext(context)
End Sub
Friend Function Clone() As ExpressionImports
Dim copy As New ExpressionImports()
copy.MyRootImport = MyRootImport.Clone()
copy.MyOwnerImport = MyOwnerImport
Return copy
End Function
Friend Sub ImportOwner(ByVal ownerType As Type)
MyOwnerImport = New TypeImport(ownerType, BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.Static, False)
MyOwnerImport.SetContext(MyContext)
End Sub
Friend Function HasNamespace(ByVal ns As String) As Boolean
Dim import As NamespaceImport = TryCast(MyRootImport.FindImport(ns), NamespaceImport)
Return Not import Is Nothing
End Function
Friend Function GetImport(ByVal ns As String) As NamespaceImport
If ns.Length = 0 Then
Return MyRootImport
End If
Dim import As NamespaceImport = TryCast(MyRootImport.FindImport(ns), NamespaceImport)
If import Is Nothing Then
import = New NamespaceImport(ns)
MyRootImport.Add(import)
End If
Return import
End Function
Friend Function FindOwnerMembers(ByVal memberName As String, ByVal memberType As System.Reflection.MemberTypes) As MemberInfo()
Return MyOwnerImport.FindMembers(memberName, memberType)
End Function
Friend Function FindType(ByVal typeNameParts As String()) As Type
Dim namespaces(typeNameParts.Length - 2) As String
Dim typeName As String = typeNameParts(typeNameParts.Length - 1)
System.Array.Copy(typeNameParts, namespaces, namespaces.Length)
Dim currentImport As ImportBase = MyRootImport
For Each ns As String In namespaces
currentImport = currentImport.FindImport(ns)
If currentImport Is Nothing Then
Exit For
End If
Next
If currentImport Is Nothing Then
Return Nothing
Else
Return currentImport.FindType(typeName)
End If
End Function
Friend Shared Function GetBuiltinType(ByVal name As String) As Type
Dim t As Type = Nothing
If OurBuiltinTypeMap.TryGetValue(name, t) = True Then
Return t
Else
Return Nothing
End If
End Function
#End Region
#Region "Methods - Public"
'''
Public Sub AddType(ByVal t As Type, ByVal ns As String)
Utility.AssertNotNull(t, "t")
Utility.AssertNotNull(ns, "namespace")
MyContext.AssertTypeIsAccessible(t)
Dim import As NamespaceImport = Me.GetImport(ns)
import.Add(New TypeImport(t, BindingFlags.Public Or BindingFlags.Static, False))
End Sub
'''
Public Sub AddType(ByVal t As Type)
Me.AddType(t, String.Empty)
End Sub
'''
Public Sub AddMethod(ByVal methodName As String, ByVal t As Type, ByVal ns As String)
Utility.AssertNotNull(methodName, "methodName")
Utility.AssertNotNull(t, "t")
Utility.AssertNotNull(ns, "namespace")
Dim mi As MethodInfo = t.GetMethod(methodName, BindingFlags.Public Or BindingFlags.Static Or BindingFlags.IgnoreCase)
If mi Is Nothing Then
Dim msg As String = Utility.GetGeneralErrorMessage(GeneralErrorResourceKeys.CouldNotFindPublicStaticMethodOnType, methodName, t.Name)
Throw New ArgumentException(msg)
End If
Me.AddMethod(mi, ns)
End Sub
'''
Public Sub AddMethod(ByVal mi As MethodInfo, ByVal ns As String)
Utility.AssertNotNull(mi, "mi")
Utility.AssertNotNull(ns, "namespace")
MyContext.AssertTypeIsAccessible(mi.ReflectedType)
If mi.IsStatic = False Or mi.IsPublic = False Then
Dim msg As String = Utility.GetGeneralErrorMessage(GeneralErrorResourceKeys.OnlyPublicStaticMethodsCanBeImported)
Throw New ArgumentException(msg)
End If
Dim import As NamespaceImport = Me.GetImport(ns)
import.Add(New MethodImport(mi))
End Sub
'''
Public Sub ImportBuiltinTypes()
For Each pair As KeyValuePair(Of String, Type) In OurBuiltinTypeMap
Me.AddType(pair.Value, pair.Key)
Next
End Sub
#End Region
#Region "Properties - Public"
'''
Public ReadOnly Property RootImport() As NamespaceImport
Get
Return MyRootImport
End Get
End Property
#End Region
End Class