microsoft-visualbasic-runtime/Scripting/InputHandler.vb

381 lines
16 KiB
VB.net
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#Region "Microsoft.VisualBasic::977e2800b5b5a1a01e74f93e04fd092e, Microsoft.VisualBasic.Core\Scripting\InputHandler.vb"
' Author:
'
' asuka (amethyst.asuka@gcmodeller.org)
' xie (genetics@smrucc.org)
' xieguigang (xie.guigang@live.com)
'
' Copyright (c) 2018 GPL3 Licensed
'
'
' GNU GENERAL PUBLIC LICENSE (GPL3)
'
'
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program 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 General Public License for more details.
'
' You should have received a copy of the GNU General Public License
' along with this program. If not, see <http://www.gnu.org/licenses/>.
' /********************************************************************************/
' Summaries:
' Module InputHandler
'
' Properties: [String], CasterString, Types
'
' Function: [DirectCast], (+3 Overloads) [GetType], (+2 Overloads) CastArray, Convertible, (+2 Overloads) CTypeDynamic
' DefaultTextParser, IsPrimitive, StringParser, (+2 Overloads) ToString
'
' Sub: CapabilityPromise
'
'
' /********************************************************************************/
#End Region
Imports System.Array
Imports System.Drawing
Imports System.IO
Imports System.Reflection
Imports System.Runtime.CompilerServices
Imports System.Text
Imports System.Text.RegularExpressions
Imports Microsoft.VisualBasic.ApplicationServices.Debugging.Logging
Imports Microsoft.VisualBasic.ComponentModel.Collection
Imports Microsoft.VisualBasic.ComponentModel.Ranges.Model
Imports Microsoft.VisualBasic.Imaging
Imports Microsoft.VisualBasic.Language
Imports Microsoft.VisualBasic.Language.Default
Imports Microsoft.VisualBasic.Scripting.Runtime
Imports Microsoft.VisualBasic.Serialization
Imports CLI = Microsoft.VisualBasic.CommandLine.CommandLine
Namespace Scripting
''' <summary>
''' Handles the input text string from commandline or scripting, dealing with the
''' conversion of this input string to .NET object in a more easy way.
''' (转换从终端或者脚本文件之中输入的字符串的类型的转换)
''' </summary>
Public Module InputHandler
''' <summary>
''' Object为字符串类型这个字典可以讲字符串转为目标类型
''' </summary>
''' <remarks></remarks>
Public ReadOnly Property CasterString As New Dictionary(Of Type, LoadObject) From {
_
{GetType(String), Function(s$) s},
{GetType(Char), AddressOf Casting.CastChar},
{GetType(Integer), AddressOf Casting.CastInteger},
{GetType(Double), AddressOf Casting.ParseNumeric},
{GetType(Long), AddressOf Casting.CastLong},
{GetType(Boolean), AddressOf ParseBoolean},
{GetType(Char()), AddressOf Casting.CastCharArray},
{GetType(Date), AddressOf Casting.CastDate},
{GetType(StringBuilder), AddressOf Casting.CastStringBuilder},
{GetType(CLI), AddressOf Casting.CastCommandLine},
{GetType(Image), AddressOf Casting.CastImage},
{GetType(FileInfo), AddressOf Casting.CastFileInfo},
{GetType(Graphics2D), AddressOf Casting.CastGDIPlusDeviceHandle},
{GetType(Color), AddressOf TranslateColor},
{GetType(Font), AddressOf Casting.CastFont},
{GetType(System.Net.IPEndPoint), AddressOf Casting.CastIPEndPoint},
{GetType(LogFile), AddressOf Casting.CastLogFile},
{GetType(Process), AddressOf Casting.CastProcess},
{GetType(RegexOptions), AddressOf Casting.CastRegexOptions},
{GetType(Single), AddressOf Casting.CastSingle},
{GetType(Decimal), Function(x) CDec(x)},
{GetType(Point), AddressOf PointParser},
{GetType(PointF), AddressOf FloatPointParser},
{GetType(Size), AddressOf SizeParser},
{GetType(SizeF), AddressOf FloatSizeParser},
{GetType(DoubleRange), AddressOf NumericRangeParser}
}
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Public Function StringParser(type As Type) As [Default](Of Func(Of String, Object))
Return New Func(Of String, Object)(Function(s$) s.CTypeDynamic(type))
End Function
''' <summary>
''' Converts a string expression which was input from the console or script file to the specified type.
''' (请注意,函数只是转换最基本的数据类型,转换错误会返回空值,空字符串也会返回空值)
''' </summary>
''' <param name="expression">The string expression to convert.</param>
''' <param name="target">The type to which to convert the object.</param>
''' <returns>An object whose type at run time is the requested target type.</returns>
<Extension> Public Function CTypeDynamic(expression$, target As Type) As Object
If expression.StringEmpty Then
Return Nothing
End If
If _CasterString.ContainsKey(target) Then
Dim caster As LoadObject = _CasterString(target)
Return caster(expression$)
End If
Static errCaster As New Index(Of String)
If expression.Length < 100 Then
' 过长的字符串在内存之中累积下来可能会导致内存溢出
' 在这里对表达式做下长度限制
If errCaster.IndexOf(expression & "|" & target.FullName) > -1 Then
' This is a exists error
Return Nothing
End If
End If
Try
Return Conversion.CTypeDynamic(expression, target)
Catch ex As Exception
If expression.Length < 100 Then
errCaster.Add(expression & "|" & target.FullName)
End If
ex = New Exception($"{expression} ==> {target.FullName}", ex)
Call App.LogException(ex, MethodBase.GetCurrentMethod.GetFullName)
Return Nothing
End Try
End Function
''' <summary>
''' Converts a string expression which was input from the console or script file to the specified type.
''' (请注意,函数只是转换最基本的数据类型,转换错误会返回空值)
''' </summary>
''' <param name="expr">The string expression to convert.</param>
''' <typeparam name="T">The type to which to convert the object.</typeparam>
''' <returns>An object whose type at run time is the requested target type.</returns>
<Extension> Public Function CTypeDynamic(Of T)(expr$, Optional [default] As T = Nothing) As T
Dim value As Object = CTypeDynamic(expr, GetType(T))
If value Is Nothing Then
Return [default]
Else
Return DirectCast(value, T)
End If
End Function
''' <summary>
''' 默认的字符串解析方法为<see cref="CTypeDynamic"/>脚本值动态转换函数
''' </summary>
''' <typeparam name="T"></typeparam>
''' <returns></returns>
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Public Function DefaultTextParser(Of T)() As [Default](Of IStringParser(Of T))
Return New IStringParser(Of T)(AddressOf CTypeDynamic(Of T)).AsDefault
End Function
''' <summary>
''' Does this type can be cast from the <see cref="String"/> type?(目标类型能否由字符串转换过来??)
''' </summary>
''' <param name="targetType"></param>
''' <returns></returns>
'''
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Public Function IsPrimitive(targetType As Type) As Boolean
Return CasterString.ContainsKey(targetType)
End Function
''' <summary>
''' Dynamics updates the capability of function <see cref="InputHandler.CTypeDynamic(String, Type)"/>,
''' <see cref="InputHandler.CTypeDynamic(Of T)(String, T)"/> and
''' <see cref="InputHandler.IsPrimitive(Type)"/>
''' </summary>
''' <param name="briefName"></param>
''' <param name="stringConvertType"></param>
''' <param name="cast"></param>
Public Sub CapabilityPromise(briefName$, stringConvertType As Type, cast As LoadObject)
With _CasterString
If .ContainsKey(stringConvertType) Then
Call .Remove(stringConvertType)
End If
Call .Add(stringConvertType, cast)
End With
Dim key$ = briefName.ToLower
If Types.ContainsKey(key) Then
Call Types.Remove(key)
End If
Call Types.Add(key, stringConvertType)
End Sub
''' <summary>
''' Enumerate all of the types that can be handled in this module. All of the key string is in lower case.(键值都是小写的)
''' </summary>
Public ReadOnly Property Types As New SortedDictionary(Of String, Type) From {
_
{"string", GetType(String)},
{"char", GetType(Char)},
{"integer", GetType(Integer)},
{"int32", GetType(Integer)},
{"int64", GetType(Long)},
{"long", GetType(Long)},
{"double", GetType(Double)},
{"single", GetType(Single)},
{"byte", GetType(Byte)},
{"date", GetType(Date)},
{"logfile", GetType(LogFile)},
{"color", GetType(Color)},
{"process", GetType(Process)},
{"font", GetType(Font)},
{"image", GetType(Image)},
{"fileinfo", GetType(IO.FileInfo)},
{"ipaddress", GetType(System.Net.IPAddress)},
{"commandline", GetType(CLI)},
{"gdi+", GetType(Graphics2D)},
{"stringbuilder", GetType(StringBuilder)},
{"boolean", GetType(Boolean)},
{"char()", GetType(Char())},
{"string()", GetType(String())},
{"integer()", GetType(Integer())},
{"double()", GetType(Double())},
{"bitmap", GetType(Bitmap)},
{"object", GetType(Object)},
{"regexoptions", GetType(RegexOptions)}
}
''' <summary>
''' Get .NET <see cref="Type"/> definition info from its name.
''' (类型获取失败会返回空值,大小写不敏感)
''' </summary>
''' <param name="name">Case insensitive.(类型的名称简写)</param>
''' <param name="ObjectGeneric">是否出错的时候返回<see cref="Object"/>类型默认返回Nothing</param>
''' <returns></returns>
Public Function [GetType](name As String, Optional objectGeneric As Boolean = False) As Type
Dim lowers = Strings.LCase(name)
If Types.ContainsKey(lowers) Then
Return Types(lowers)
Else
Dim typeInfo As Type = Type.GetType(name, False, True)
If typeInfo Is Nothing AndAlso objectGeneric Then
Return GetType(Object)
Else
Return typeInfo
End If
End If
End Function
''' <summary>
''' Get .NET <see cref="Type"/> definition info from its name.
''' (类型获取失败会返回空值,大小写不敏感)
''' </summary>
''' <param name="name">Case insensitive.(类型的名称简写)</param>
''' <param name="ObjectGeneric">是否出错的时候返回<see cref="Object"/>类型默认返回Nothing</param>
''' <returns></returns>
'''
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Public Function [GetType](name As Value(Of String), Optional objectGeneric As Boolean = False) As Type
Return Scripting.GetType(name.Value, objectGeneric)
End Function
Public Function [GetType](obj As Object, Optional ObjectGeneric As Boolean = False) As Type
If obj Is Nothing Then
If ObjectGeneric Then
Return GetType(Object)
Else
Return Nothing
End If
Else
Return obj.GetType
End If
End Function
''' <summary>
''' <see cref="System.Type"/> information for <see cref="System.String"/> type from GetType operator
''' </summary>
''' <returns></returns>
Public ReadOnly Property [String] As Type = GetType(String)
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Public Function ToString(Of T)() As [Default](Of IToString(Of T))
Return New IToString(Of T)(AddressOf ToString)
End Function
''' <summary>
''' Does the <paramref name="inputtype"/> type can be cast to type <paramref name="DefType"/>.
''' (主要为了方便减少脚本编程模块的代码)
''' </summary>
''' <param name="inputType"></param>
''' <param name="DefType"></param>
''' <returns></returns>
'''
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Public Function Convertible(inputType As Type, DefType As Type) As Boolean
Return inputType.Equals([String]) AndAlso CasterString.ContainsKey(DefType)
End Function
''' <summary>
''' <seealso cref="CStrSafe"/>, 出现错误的时候总是会返回空字符串的,
'''
''' 注意:
'''
''' 1. 对于一些基础的数据类型例如<see cref="Integer"/>,<see cref="Long"/>等则是以json序列化来构建字符串值
''' 2. 对于<see cref="Byte"/>数组则是被编码为base64字符串
''' </summary>
''' <param name="obj"></param>
''' <returns></returns>
'''
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Public Function ToString(obj As Object, Optional null$ = "") As String
Return CStrSafe(obj, null)
End Function
''' <summary>
''' The parameter <paramref name="obj"/> should implements a <see cref="IEnumerable"/> interface on the type. and then DirectCast object to target type.
''' </summary>
''' <typeparam name="T"></typeparam>
''' <param name="obj"></param>
''' <returns></returns>
Public Function CastArray(Of T)(obj As Object) As T()
Dim array = DirectCast(obj, IEnumerable)
Dim data = (From val In array Select DirectCast(val, T)).ToArray
Return data
End Function
Public Function CastArray(obj As Object, type As Type) As Object
If Array.IndexOf(obj.GetType.GetInterfaces, GetType(IEnumerable)) = -1 Then
Return obj
End If
Dim source As IEnumerable = DirectCast(obj, IEnumerable)
Dim data = LinqAPI.Exec(Of Object) _
_
() <= From val As Object
In source
Let value = Conversion.CTypeDynamic(val, type)
Select value
Return [DirectCast](data, type)
End Function
''' <summary>
''' Cast the <see cref="Object"/> array to typed object array.
''' </summary>
''' <param name="array"></param>
''' <param name="type">数组里面的元素的类型</param>
''' <returns></returns>
Public Function [DirectCast](array As Object(), type As Type) As Object
Dim out = CreateInstance(type, array.Length)
Call Copy(array, out, array.Length) ' 直接复制不能够正常工作
Return out
End Function
End Module
End Namespace