1 #Region "Microsoft.VisualBasic::c0ca771700880fb67c3ae89a309e4876, Microsoft.VisualBasic.Core\ComponentModel\DataSource\Property\DynamicProperty.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     '     Interface IDynamicMeta
35     
36     '         Properties: Properties
37     
38     '     Class DynamicPropertyBase
39     
40     '         Properties: MyHashCode, Properties
41     
42     '         FunctionEnumerateKeys, HasProperty, ToString
43     
44     '     Class [Property]
45     
46     '         Constructor: (+2 OverloadsSub New
47     
48     
49     ' /********************************************************************************/
50
51 #End Region
52
53 Imports System.Runtime.CompilerServices
54 Imports System.Web.Script.Serialization
55 Imports System.Xml.Serialization
56 Imports Microsoft.VisualBasic.Language
57 Imports Microsoft.VisualBasic.Linq
58
59 Namespace ComponentModel.DataSourceModel
60
61     ''' <summary>
62     ''' Abstracts for the dynamics property.
63     ''' </summary>
64     ''' <typeparam name="T"></typeparam>
65     Public Interface IDynamicMeta(Of T)
66
67         ''' <summary>
68         ''' Properties
69         ''' </summary>
70         ''' <returns></returns>
71         Property Properties As Dictionary(Of String, T)
72     End Interface
73
74     ''' <summary>
75     ''' This abstract object has a <see cref="propertyTable"/> dictionary keeps as a dynamics property source.
76     ''' </summary>
77     ''' <typeparam name="T"></typeparam>
78     Public MustInherit Class DynamicPropertyBase(Of T)
79         Implements IDynamicMeta(Of T)
80
81         ''' <summary>
82         ''' The dynamics property object with specific type of value.
83         ''' </summary>
84         ''' <returns></returns>
85         ''' <remarks>Can not serialize the dictionary object in to xml document.</remarks>
86         <XmlIgnore> Public Overridable Property Properties As Dictionary(Of String, T) Implements IDynamicMeta(Of T).Properties
87             Get
88                 If propertyTable Is Nothing Then
89                     propertyTable = New Dictionary(Of String, T)
90                 End If
91                 Return propertyTable
92             End Get
93             Set(value As Dictionary(Of String, T))
94                 propertyTable = value
95             End Set
96         End Property
97
98         ''' <summary>
99         ''' 动态属性表
100         ''' </summary>
101         Dim propertyTable As Dictionary(Of String, T)
102
103         ''' <summary>
104         ''' Gets/sets item value by using property name.
105         ''' (这个函数为安全的函数,当目标属性不存在的时候,会返回空值)
106         ''' </summary>
107         ''' <param name="name"></param>
108         ''' <returns></returns>
109         Default Public Overloads Property ItemValue(name$) As T
110             <MethodImpl(MethodImplOptions.AggressiveInlining)>
111             Get
112                 If Properties.ContainsKey(name) Then
113                     Return Properties(name)
114                 Else
115                     Return Nothing
116                 End If
117             End Get
118             Set(value As T)
119                 Properties(name) = value
120             End Set
121         End Property
122
123         ''' <summary>
124         ''' Get a value package at once using a key collection, 
125         ''' if the key is not exists in the property, then its 
126         ''' correspoding value is nothing.
127         ''' </summary>
128         ''' <param name="keys"></param>
129         ''' <returns></returns>
130         Default Public Overloads Property ItemValue(keys As IEnumerable(Of String)) As T()
131             <MethodImpl(MethodImplOptions.AggressiveInlining)>
132             Get
133                 Return keys.Select(Function(s) Me(s)).ToArray
134             End Get
135             Set(value As T())
136                 For Each key As SeqValue(Of StringIn keys.SeqIterator
137                     Me(key.value) = value(key)
138                 Next
139             End Set
140         End Property
141
142         ''' <summary>
143         ''' Determines whether the System.Collections.Generic.Dictionary`2 contains the specified
144         ''' key.
145         ''' </summary>
146         ''' <param name="name$">The key to locate in the System.Collections.Generic.Dictionary`2.</param>
147         ''' <returns>
148         ''' true if the System.Collections.Generic.Dictionary`2 contains an element with
149         ''' the specified key; otherwise, false.
150         ''' </returns>
151         Public Function HasProperty(name$) As Boolean
152             If propertyTable Is Nothing Then
153                 Return False
154             Else
155                 Return propertyTable.ContainsKey(name)
156             End If
157         End Function
158
159         ''' <summary>
160         ''' 枚举这个动态字典类型之中的所有的键名,这个函数是默认不包含有类型自有的属性名称的
161         ''' </summary>
162         ''' <param name="joinProperties">是否包括属性名称,默认不包含</param>
163         ''' <returns></returns>
164         Public Function EnumerateKeys(Optional joinProperties As Boolean = FalseAs String()
165             Dim out As New List(Of String)
166
167             If joinProperties Then
168                 out += MyClass.GetType _
169                     .GetProperties(PublicProperty) _
170                     .Where(Function(p) p.GetIndexParameters.IsNullOrEmpty) _
171                     .Select(Function(p) p.Name) _
172                     .ToArray
173             End If
174
175             If Not propertyTable Is Nothing Then
176                 out += propertyTable.Keys
177             End If
178
179             Return out.Distinct.ToArray
180         End Function
181
182         Public Overrides Function ToString() As String
183             Return $"{Properties.Count} Property(s)."
184         End Function
185
186         ''' <summary>
187         ''' Using for debugger view, this property is usually usefull for the dictionary view 
188         ''' to see if any duplicated was existed? 
189         ''' </summary>
190         ''' <returns></returns>
191         Protected Overridable ReadOnly Property MyHashCode As Integer
192             <MethodImpl(MethodImplOptions.AggressiveInlining)>
193             Get
194                 Return GetHashCode()
195             End Get
196         End Property
197     End Class
198
199     ''' <summary>
200     ''' Dictionary for [<see cref="String"/>, <typeparamref name="T"/>]
201     ''' </summary>
202     ''' <typeparam name="T"></typeparam>
203     Public Class [Property](Of T) : Inherits DynamicPropertyBase(Of T)
204
205         Sub New()
206         End Sub
207
208         ''' <summary>
209         ''' New with a init property value
210         ''' </summary>
211         ''' <param name="initKey"></param>
212         ''' <param name="initValue"></param>
213         Sub New(initKey$, initValue As T)
214             Call Properties.Add(initKey, initValue)
215         End Sub
216
217         ''' <summary>
218         ''' 
219         ''' </summary>
220         ''' <returns></returns>
221         <ScriptIgnore> Public Iterator Property src As IEnumerable(Of NamedValue(Of T))
222             Get
223                 For Each x In Properties
224                     Yield New NamedValue(Of T) With {
225                         .Name = x.Key,
226                         .Value = x.Value
227                     }
228                 Next
229             End Get
230             <MethodImpl(MethodImplOptions.AggressiveInlining)>
231             Set(value As IEnumerable(Of NamedValue(Of T)))
232                 Properties = value.ToDictionary(Function(x) x.Name, Function(x) x.Value)
233             End Set
234         End Property
235     End Class
236 End Namespace