1 | #Region "Microsoft.VisualBasic::633a486a87f1e57733543dbb7304615f, Microsoft.VisualBasic.Core\ComponentModel\DataSource\SchemaMaps\DataSource.vb" |
2 | |
3 | ' Author: |
4 | ' |
5 | ' asuka (amethyst.asuka@gcmodeller.org) |
6 | ' xie (genetics@smrucc.org) |
7 | ' xieguigang (xie.guigang@live.com) |
8 | ' |
9 | ' Copyright (c) 2018 GPL3 Licensed |
10 | ' |
11 | ' |
12 | ' GNU GENERAL PUBLIC LICENSE (GPL3) |
13 | ' |
14 | ' |
15 | ' This program is free software: you can redistribute it and/or modify |
16 | ' it under the terms of the GNU General Public License as published by |
17 | ' the Free Software Foundation, either version 3 of the License, or |
18 | ' (at your option) any later version. |
19 | ' |
20 | ' This program is distributed in the hope that it will be useful, |
21 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of |
22 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
23 | ' GNU General Public License for more details. |
24 | ' |
25 | ' You should have received a copy of the GNU General Public License |
26 | ' along with this program. If not, see <http://www.gnu.org/licenses/>. |
27 | |
28 | |
29 | |
30 | ' /********************************************************************************/ |
31 | |
32 | ' Summaries: |
33 | |
34 | ' Class Field |
35 | ' |
36 | ' Constructor: (+1 Overloads) Sub New |
37 | ' |
38 | ' Class DataFrameColumnAttribute |
39 | ' |
40 | ' Properties: Description, Index, Name |
41 | ' |
42 | ' Constructor: (+4 Overloads) Sub New |
43 | ' Function: __attrs, __attrsAll, __source, GetIndex, GetMapping |
44 | ' (+2 Overloads) LoadMapping, SetNameValue, ToString |
45 | ' |
46 | ' Class DataFrameIO |
47 | ' |
48 | ' |
49 | ' |
50 | ' |
51 | ' /********************************************************************************/ |
52 | |
53 | #End Region |
54 | |
55 | Imports System.Reflection |
56 | Imports System.Runtime.CompilerServices |
57 | Imports Microsoft.VisualBasic.ComponentModel.Collection |
58 | Imports Microsoft.VisualBasic.Language |
59 | Imports FieldTuple = System.Collections.Generic.KeyValuePair(Of Microsoft.VisualBasic.ComponentModel.DataSourceModel.SchemaMaps.DataFrameColumnAttribute, System.Reflection.PropertyInfo) |
60 | |
61 | Namespace ComponentModel.DataSourceModel.SchemaMaps |
62 | |
63 | ''' <summary> |
64 | ''' <see cref="DataFrameColumnAttribute"/>属性的别称 |
65 | ''' </summary> |
66 | Public Class Field : Inherits DataFrameColumnAttribute |
67 | |
68 | ''' <summary> |
69 | ''' Initializes a new instance by name. |
70 | ''' </summary> |
71 | ''' <param name="FieldName">The name.</param> |
72 | ''' |
73 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
74 | Public Sub New(FieldName As String) |
75 | Call MyBase.New(FieldName) |
76 | End Sub |
77 | End Class |
78 | |
79 | ''' <summary> |
80 | ''' Represents a column of certain data frames. The mapping between to schema is also can be represent by this attribute. |
81 | ''' (也可以使用这个对象来完成在两个数据源之间的属性的映射,由于对于一些列名称的属性值缺失的映射而言, |
82 | ''' 其是使用属性名来作为列映射名称的,故而在修改这些没有预设的列名称的映射属性的属性名的时候,请注意 |
83 | ''' 要小心维护这种映射关系) |
84 | ''' </summary> |
85 | <AttributeUsage(AttributeTargets.[Property] Or AttributeTargets.Field, |
86 | Inherited:=True, |
87 | AllowMultiple:=False)> |
88 | Public Class DataFrameColumnAttribute : Inherits Attribute |
89 | |
90 | Protected Shared ReadOnly __emptyIndex As String() = New String(-1) {} |
91 | |
92 | ''' <summary> |
93 | ''' Gets the index. |
94 | ''' </summary> |
95 | Public ReadOnly Property Index() As Integer |
96 | |
97 | ''' <summary> |
98 | ''' Gets the name. |
99 | ''' </summary> |
100 | Public ReadOnly Property Name() As String |
101 | |
102 | Public Property Description As String |
103 | |
104 | ''' <summary> |
105 | ''' Initializes a new instance by name. |
106 | ''' </summary> |
107 | ''' <param name="FieldName">The name.</param> |
108 | Public Sub New(FieldName As String) |
109 | If String.IsNullOrEmpty(FieldName) Then |
110 | Throw New ArgumentNullException(NameOf(FieldName)) |
111 | End If |
112 | Me._Name = FieldName |
113 | Me._Index = -1 |
114 | End Sub |
115 | |
116 | ''' <summary> |
117 | ''' Initializes a new instance by index. |
118 | ''' </summary> |
119 | ''' <param name="index">The index.</param> |
120 | Public Sub New(index As Integer) |
121 | If index < 0 Then |
122 | Throw New ArgumentOutOfRangeException(NameOf(index)) |
123 | End If |
124 | Me._Name = Nothing |
125 | Me._Index = index |
126 | End Sub |
127 | |
128 | ''' <summary> |
129 | ''' 会默认使用目标对象的反射的Name属性作为映射的名称 |
130 | ''' </summary> |
131 | ''' <remarks></remarks> |
132 | Public Sub New() |
133 | _Index = -1 |
134 | End Sub |
135 | |
136 | ''' <summary> |
137 | ''' |
138 | ''' </summary> |
139 | ''' <param name="Name">列名称,假若本参数为空的话,则使用属性名称</param> |
140 | ''' <param name="index">从1开始的下标,表示为第几列</param> |
141 | ''' <remarks></remarks> |
142 | Sub New(Optional Name As String = "", Optional index As Integer = -1) |
143 | _Name = Name |
144 | _Index = index |
145 | End Sub |
146 | |
147 | Public Overrides Function ToString() As String |
148 | Return _Name |
149 | End Function |
150 | |
151 | Const NameException As String = "Name must not be null when Index is not defined." |
152 | |
153 | Public Function SetNameValue(value As String) As DataFrameColumnAttribute |
154 | If Me._Index < 0 AndAlso String.IsNullOrEmpty(value) Then |
155 | Throw New ArgumentNullException(NameOf(value), NameException) |
156 | End If |
157 | Me._Name = value |
158 | Return Me |
159 | End Function |
160 | |
161 | Public Function GetIndex(names As String()) As Integer |
162 | Return If(Index >= 0, Index, Array.IndexOf(If(names, __emptyIndex), Name)) |
163 | End Function |
164 | |
165 | ''' <summary> |
166 | ''' 没有名称属性的映射使用属性名来表述,请注意,字典的Key是属性的名称 |
167 | ''' </summary> |
168 | ''' <typeparam name="T"></typeparam> |
169 | ''' <returns></returns> |
170 | ''' <remarks></remarks> |
171 | ''' |
172 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
173 | Public Shared Function LoadMapping(Of T)( |
174 | Optional ignores As String() = Nothing, |
175 | Optional mapsAll As Boolean = False) _ |
176 | As Dictionary(Of BindProperty(Of DataFrameColumnAttribute)) |
177 | |
178 | Return LoadMapping(GetType(T), ignores, mapsAll) |
179 | End Function |
180 | |
181 | ''' <summary> |
182 | ''' Load the mapping property, if the custom attribute <see cref="DataFrameColumnAttribute"></see> |
183 | ''' have no name value, then the property name will be used as the mapping name. |
184 | ''' (这个函数会自动给空名称值进行属性名的赋值操作的) |
185 | ''' </summary> |
186 | ''' <param name="typeInfo">The type should be a class type or its properties should have the |
187 | ''' mapping option which was created by the custom attribute <see cref="DataFrameColumnAttribute"></see> |
188 | ''' </param> |
189 | ''' <param name="ignores">这个是大小写敏感的</param> |
190 | ''' <returns></returns> |
191 | ''' <remarks></remarks> |
192 | Public Shared Function LoadMapping( |
193 | typeInfo As Type, |
194 | Optional ignores As String() = Nothing, |
195 | Optional mapsAll As Boolean = False) _ |
196 | As Dictionary(Of BindProperty(Of DataFrameColumnAttribute)) |
197 | |
198 | Dim ignoreList$() = If(ignores Is Nothing, {}, ignores) |
199 | Dim source As IEnumerable(Of FieldTuple) = __source(typeInfo, ignoreList, mapsAll) |
200 | Dim LQuery = LinqAPI.Exec(Of BindProperty(Of DataFrameColumnAttribute)) _ |
201 | _ |
202 | () <= From pInfo As FieldTuple |
203 | In source |
204 | Let Mapping As DataFrameColumnAttribute = GetMapping(pInfo) |
205 | Select New BindProperty(Of DataFrameColumnAttribute)(Mapping, pInfo.Value) ' 补全名称属性 |
206 | |
207 | Dim out As New Dictionary(Of BindProperty(Of DataFrameColumnAttribute))(LQuery) |
208 | Return out |
209 | End Function |
210 | |
211 | ''' <summary> |
212 | ''' 假若名称是空的,则会在这里自动的使用属性名称进行赋值 |
213 | ''' </summary> |
214 | ''' <param name="pinfo"></param> |
215 | ''' <returns></returns> |
216 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
217 | Private Shared Function GetMapping(pinfo As FieldTuple) As DataFrameColumnAttribute |
218 | If String.IsNullOrEmpty(pinfo.Key.Name) Then |
219 | Return pinfo.Key.SetNameValue(pinfo.Value.Name) |
220 | Else |
221 | Return pinfo.Key |
222 | End If |
223 | End Function |
224 | |
225 | ''' <summary> |
226 | ''' |
227 | ''' </summary> |
228 | ''' <param name="type"></param> |
229 | ''' <param name="ignores$"></param> |
230 | ''' <param name="mapsAll"> |
231 | ''' Some property probably didn't have masked by <see cref="DataFrameColumnAttribute"/>, |
232 | ''' so if this option is set to TRUE, then means indexing these property that without <see cref="DataFrameColumnAttribute"/> masked as well. |
233 | ''' otherwise only indexing the property that have <see cref="DataFrameColumnAttribute"/> masked on it. |
234 | ''' </param> |
235 | ''' <returns></returns> |
236 | Private Shared Iterator Function __source(type As Type, ignores$(), mapsAll As Boolean) As IEnumerable(Of FieldTuple) |
237 | Dim props As IEnumerable(Of PropertyInfo) = |
238 | _ |
239 | From p As PropertyInfo |
240 | In type.GetProperties(BindingFlags.Public Or BindingFlags.Instance) |
241 | Where Array.IndexOf(ignores, p.Name) = -1 |
242 | Select p |
243 | |
244 | If Not mapsAll Then |
245 | For Each x In From pInfo As PropertyInfo |
246 | In props |
247 | Let attrs As Object() = __attrs(pInfo) |
248 | Where Not attrs.IsNullOrEmpty |
249 | Let attr = DirectCast(attrs.First, DataFrameColumnAttribute) |
250 | Select New FieldTuple(attr, pInfo) |
251 | Yield x |
252 | Next |
253 | Else |
254 | For Each x In From pInfo As PropertyInfo |
255 | In props |
256 | Let attr = __attrsAll(pInfo) |
257 | Select New FieldTuple(attr, pInfo) |
258 | Yield x |
259 | Next |
260 | End If |
261 | End Function |
262 | |
263 | Private Shared Function __attrsAll(pp As PropertyInfo) As DataFrameColumnAttribute |
264 | Dim attrs() = __attrs(pp) |
265 | |
266 | If attrs.IsNullOrEmpty Then |
267 | Return New DataFrameColumnAttribute |
268 | Else |
269 | Return attrs(Scan0) |
270 | End If |
271 | End Function |
272 | |
273 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
274 | Public Shared Function __attrs(pp As PropertyInfo) As DataFrameColumnAttribute() |
275 | Return pp _ |
276 | .GetCustomAttributes(GetType(DataFrameColumnAttribute), True) _ |
277 | .Select(Function(o) DirectCast(o, DataFrameColumnAttribute)) _ |
278 | .ToArray |
279 | End Function |
280 | End Class |
281 | |
282 | Public MustInherit Class DataFrameIO(Of TAttributeType As DataFrameColumnAttribute) |
283 | |
284 | ''' <summary> |
285 | ''' |
286 | ''' </summary> |
287 | ''' <returns></returns> |
288 | ''' <remarks></remarks> |
289 | Protected MustOverride Function InitializeSchema(Of TEntityType As Class)() As TAttributeType() |
290 | End Class |
291 | End Namespace |