microsoft-visualbasic-runtime/ComponentModel/DataSource/SchemaMaps/DataSource.vb

292 lines
11 KiB
VB.net
Raw Normal View History

2019-07-29 02:05:05 +08:00
#Region "Microsoft.VisualBasic::633a486a87f1e57733543dbb7304615f, Microsoft.VisualBasic.Core\ComponentModel\DataSource\SchemaMaps\DataSource.vb"
2018-08-02 20:14:48 +08:00
2018-10-06 00:02:05 +08:00
' 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/>.
2018-10-03 19:24:46 +08:00
2018-10-06 00:02:05 +08:00
' /********************************************************************************/
2018-10-03 19:24:46 +08:00
2018-10-06 00:02:05 +08:00
' Summaries:
2018-10-03 19:24:46 +08:00
2018-10-06 00:02:05 +08:00
' Class Field
'
' Constructor: (+1 Overloads) Sub New
'
' Class DataFrameColumnAttribute
'
' Properties: Description, Index, Name
'
' Constructor: (+4 Overloads) Sub New
' Function: __attrs, __attrsAll, __source, GetIndex, GetMapping
' (+2 Overloads) LoadMapping, SetNameValue, ToString
'
' Class DataFrameIO
'
'
'
'
' /********************************************************************************/
2018-08-02 20:14:48 +08:00
#End Region
Imports System.Reflection
Imports System.Runtime.CompilerServices
Imports Microsoft.VisualBasic.ComponentModel.Collection
Imports Microsoft.VisualBasic.Language
Imports FieldTuple = System.Collections.Generic.KeyValuePair(Of Microsoft.VisualBasic.ComponentModel.DataSourceModel.SchemaMaps.DataFrameColumnAttribute, System.Reflection.PropertyInfo)
Namespace ComponentModel.DataSourceModel.SchemaMaps
''' <summary>
''' <see cref="DataFrameColumnAttribute"/>属性的别称
''' </summary>
Public Class Field : Inherits DataFrameColumnAttribute
''' <summary>
''' Initializes a new instance by name.
''' </summary>
''' <param name="FieldName">The name.</param>
'''
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Public Sub New(FieldName As String)
Call MyBase.New(FieldName)
End Sub
End Class
''' <summary>
''' Represents a column of certain data frames. The mapping between to schema is also can be represent by this attribute.
''' (也可以使用这个对象来完成在两个数据源之间的属性的映射,由于对于一些列名称的属性值缺失的映射而言,
''' 其是使用属性名来作为列映射名称的,故而在修改这些没有预设的列名称的映射属性的属性名的时候,请注意
''' 要小心维护这种映射关系)
''' </summary>
<AttributeUsage(AttributeTargets.[Property] Or AttributeTargets.Field,
Inherited:=True,
AllowMultiple:=False)>
Public Class DataFrameColumnAttribute : Inherits Attribute
Protected Shared ReadOnly __emptyIndex As String() = New String(-1) {}
''' <summary>
''' Gets the index.
''' </summary>
Public ReadOnly Property Index() As Integer
''' <summary>
''' Gets the name.
''' </summary>
Public ReadOnly Property Name() As String
Public Property Description As String
''' <summary>
''' Initializes a new instance by name.
''' </summary>
''' <param name="FieldName">The name.</param>
Public Sub New(FieldName As String)
If String.IsNullOrEmpty(FieldName) Then
Throw New ArgumentNullException(NameOf(FieldName))
End If
Me._Name = FieldName
Me._Index = -1
End Sub
''' <summary>
''' Initializes a new instance by index.
''' </summary>
''' <param name="index">The index.</param>
Public Sub New(index As Integer)
If index < 0 Then
Throw New ArgumentOutOfRangeException(NameOf(index))
End If
Me._Name = Nothing
Me._Index = index
End Sub
''' <summary>
''' 会默认使用目标对象的反射的Name属性作为映射的名称
''' </summary>
''' <remarks></remarks>
Public Sub New()
_Index = -1
End Sub
''' <summary>
'''
''' </summary>
''' <param name="Name">列名称,假若本参数为空的话,则使用属性名称</param>
''' <param name="index">从1开始的下标表示为第几列</param>
''' <remarks></remarks>
Sub New(Optional Name As String = "", Optional index As Integer = -1)
_Name = Name
_Index = index
End Sub
Public Overrides Function ToString() As String
Return _Name
End Function
Const NameException As String = "Name must not be null when Index is not defined."
Public Function SetNameValue(value As String) As DataFrameColumnAttribute
If Me._Index < 0 AndAlso String.IsNullOrEmpty(value) Then
Throw New ArgumentNullException(NameOf(value), NameException)
End If
Me._Name = value
Return Me
End Function
Public Function GetIndex(names As String()) As Integer
Return If(Index >= 0, Index, Array.IndexOf(If(names, __emptyIndex), Name))
End Function
''' <summary>
''' 没有名称属性的映射使用属性名来表述请注意字典的Key是属性的名称
''' </summary>
''' <typeparam name="T"></typeparam>
''' <returns></returns>
''' <remarks></remarks>
'''
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Public Shared Function LoadMapping(Of T)(
Optional ignores As String() = Nothing,
Optional mapsAll As Boolean = False) _
As Dictionary(Of BindProperty(Of DataFrameColumnAttribute))
Return LoadMapping(GetType(T), ignores, mapsAll)
End Function
''' <summary>
''' Load the mapping property, if the custom attribute <see cref="DataFrameColumnAttribute"></see>
''' have no name value, then the property name will be used as the mapping name.
''' (这个函数会自动给空名称值进行属性名的赋值操作的)
''' </summary>
''' <param name="typeInfo">The type should be a class type or its properties should have the
''' mapping option which was created by the custom attribute <see cref="DataFrameColumnAttribute"></see>
''' </param>
''' <param name="ignores">这个是大小写敏感的</param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function LoadMapping(
typeInfo As Type,
Optional ignores As String() = Nothing,
Optional mapsAll As Boolean = False) _
As Dictionary(Of BindProperty(Of DataFrameColumnAttribute))
Dim ignoreList$() = If(ignores Is Nothing, {}, ignores)
Dim source As IEnumerable(Of FieldTuple) = __source(typeInfo, ignoreList, mapsAll)
Dim LQuery = LinqAPI.Exec(Of BindProperty(Of DataFrameColumnAttribute)) _
_
() <= From pInfo As FieldTuple
In source
2018-10-03 19:24:46 +08:00
Let Mapping As DataFrameColumnAttribute = GetMapping(pInfo)
Select New BindProperty(Of DataFrameColumnAttribute)(Mapping, pInfo.Value) ' 补全名称属性
2018-08-02 20:14:48 +08:00
Dim out As New Dictionary(Of BindProperty(Of DataFrameColumnAttribute))(LQuery)
Return out
End Function
2018-10-03 19:24:46 +08:00
''' <summary>
''' 假若名称是空的,则会在这里自动的使用属性名称进行赋值
''' </summary>
''' <param name="pinfo"></param>
''' <returns></returns>
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Private Shared Function GetMapping(pinfo As FieldTuple) As DataFrameColumnAttribute
If String.IsNullOrEmpty(pinfo.Key.Name) Then
Return pinfo.Key.SetNameValue(pinfo.Value.Name)
Else
Return pinfo.Key
End If
End Function
2018-08-02 20:14:48 +08:00
''' <summary>
'''
''' </summary>
''' <param name="type"></param>
''' <param name="ignores$"></param>
''' <param name="mapsAll">
''' Some property probably didn't have masked by <see cref="DataFrameColumnAttribute"/>,
''' so if this option is set to TRUE, then means indexing these property that without <see cref="DataFrameColumnAttribute"/> masked as well.
''' otherwise only indexing the property that have <see cref="DataFrameColumnAttribute"/> masked on it.
''' </param>
''' <returns></returns>
Private Shared Iterator Function __source(type As Type, ignores$(), mapsAll As Boolean) As IEnumerable(Of FieldTuple)
Dim props As IEnumerable(Of PropertyInfo) =
_
From p As PropertyInfo
In type.GetProperties(BindingFlags.Public Or BindingFlags.Instance)
Where Array.IndexOf(ignores, p.Name) = -1
Select p
If Not mapsAll Then
For Each x In From pInfo As PropertyInfo
In props
Let attrs As Object() = __attrs(pInfo)
Where Not attrs.IsNullOrEmpty
Let attr = DirectCast(attrs.First, DataFrameColumnAttribute)
Select New FieldTuple(attr, pInfo)
Yield x
Next
Else
For Each x In From pInfo As PropertyInfo
In props
Let attr = __attrsAll(pInfo)
Select New FieldTuple(attr, pInfo)
Yield x
Next
End If
End Function
Private Shared Function __attrsAll(pp As PropertyInfo) As DataFrameColumnAttribute
Dim attrs() = __attrs(pp)
If attrs.IsNullOrEmpty Then
Return New DataFrameColumnAttribute
Else
Return attrs(Scan0)
End If
End Function
<MethodImpl(MethodImplOptions.AggressiveInlining)>
Public Shared Function __attrs(pp As PropertyInfo) As DataFrameColumnAttribute()
Return pp _
.GetCustomAttributes(GetType(DataFrameColumnAttribute), True) _
.Select(Function(o) DirectCast(o, DataFrameColumnAttribute)) _
.ToArray
End Function
End Class
Public MustInherit Class DataFrameIO(Of TAttributeType As DataFrameColumnAttribute)
''' <summary>
'''
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Protected MustOverride Function InitializeSchema(Of TEntityType As Class)() As TAttributeType()
End Class
End Namespace