1 #Region "Microsoft.VisualBasic::fb23f87e901dbe3b09902ba28ad2c6d1, Microsoft.VisualBasic.Core\Extensions\Collection\Linq\SetValue.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     '     Structure SetValuExtension
35     
36     '         FunctionInvokeSet, ToString
37     
38     '     Class SetValue
39     
40     '         Constructor: (+1 OverloadsSub New
41     '         FunctionToString
42     '         Delegate Function
43     
44     '             FunctionGetEnumerator, GetSet, IEnumerable_GetEnumerator, InvokeSet, (+2 OverloadsInvokeSetValue
45     '             Operators: <=, >=
46     
47     
48     
49     ' /********************************************************************************/
50
51 #End Region
52
53 Imports System.Reflection
54 Imports Microsoft.VisualBasic.ComponentModel.DataSourceModel
55 Imports Microsoft.VisualBasic.Language
56 Imports Microsoft.VisualBasic.Serialization.JSON
57
58 Namespace Linq
59
60     Public Structure SetValuExtension(Of T)
61         Public schema As SetValue(Of T)
62         Public obj As T
63
64         ''' <summary>
65         ''' 
66         ''' </summary>
67         ''' <param name="name">Using NameOf</param>
68         ''' <param name="value"></param>
69         ''' <returns></returns>
70         Public Function InvokeSet(name As String, value As ObjectAs SetValuExtension(Of T)
71             Return schema.InvokeSetValue(obj, name, value)
72         End Function
73
74         Public Overrides Function ToString() As String
75             Return obj.GetJson
76         End Function
77
78         Public Shared Narrowing Operator CType(x As SetValuExtension(Of T)) As T
79             Return x.obj
80         End Operator
81     End Structure
82
83     ''' <summary>
84     ''' Set value linq expression helper
85     ''' </summary>
86     Public Class SetValue(Of T) : Implements IEnumerable(Of PropertyInfo)
87
88         ReadOnly __type As Type = GetType(T)
89         ReadOnly __props As SortedDictionary(Of StringPropertyInfo)
90
91         Sub New()
92             __props = New SortedDictionary(Of StringPropertyInfo)(
93                 DataFramework.Schema(Of T)(
94                 PropertyAccess.Writeable))
95         End Sub
96
97         Public Overrides Function ToString() As String
98             Return __type.ToString
99         End Function
100
101         Public Delegate Function IInvokeSetValue(x As T, value As ObjectAs T
102
103         ''' <summary>
104         ''' Public Delegate Function IInvokeSetValue(x As T, value As ObjectAs T
105         ''' </summary>
106         ''' <param name="name">Using NameOf</param>
107         ''' <returns></returns>
108         Public Function GetSet(name As StringAs IInvokeSetValue
109             Dim setValue As PropertyInfo = __props(name)
110             Return Function(x, v)
111                        Call setValue.SetValue(x, v)
112                        Return x
113                    End Function
114         End Function
115
116         ''' <summary>
117         ''' <see cref="GetSet"/>
118         ''' </summary>
119         ''' <param name="setValue"></param>
120         ''' <param name="name">Using NameOf</param>
121         ''' <returns></returns>
122         Public Shared Operator <=(setValue As SetValue(Of T), name As StringAs IInvokeSetValue
123             Return setValue.GetSet(name)
124         End Operator
125
126         Public Shared Operator >=(setValue As SetValue(Of T), name As StringAs IInvokeSetValue
127             Throw New NotSupportedException
128         End Operator
129
130         ''' <summary>
131         ''' Assigning the value to the specific named property to the target object.
132         ''' (将<paramref name="value"/>参数之中的值赋值给目标对象<paramref name="x"/>之中的指定的<paramref name="name"/>属性名称的属性,
133         ''' 如果发生错误,则原有的对象<paramref name="x"/>不会被修改)
134         ''' </summary>
135         ''' <param name="x"></param>
136         ''' <param name="name">Using NameOf.(可以使用NameOf得到需要进行修改的属性名称)</param>
137         ''' <param name="value"></param>
138         ''' <returns></returns>
139         Public Function InvokeSetValue(x As T, name As String, value As ObjectAs SetValuExtension(Of T)
140             If __props.ContainsKey(name) Then
141                 Dim setValue As PropertyInfo = __props(name)
142                 Call setValue.SetValue(x, value)
143             Else
144                 Dim lstName As String = String.Join("; ", __props.Keys.ToArray)
145                 VBDebugger.Warning($"Could Not found the target parameter which is named {name} // {lstName}")
146             End If
147
148             Return New SetValuExtension(Of T) With {
149                 .schema = Me,
150                 .obj = x
151             }
152         End Function
153
154         Public Function InvokeSetValue(x As T, value As NamedValue(Of Object)) As T
155             Return InvokeSetValue(x, value.Name, value.Value)
156         End Function
157
158         ''' <summary>
159         ''' Assigning the value to the specific named property to the target object.
160         ''' (将<paramref name="value"/>参数之中的值赋值给目标对象<paramref name="obj"/>之中的指定的<paramref name="name"/>属性名称的属性,
161         ''' 如果发生错误,则原有的对象<paramref name="obj"/>不会被修改)
162         ''' </summary>
163         ''' <typeparam name="Tvalue"></typeparam>
164         ''' <param name="obj"></param>
165         ''' <param name="Name">可以使用NameOf得到需要进行修改的属性名称</param>
166         ''' <param name="value"></param>
167         ''' <returns></returns>
168         Public Shared Function InvokeSet(Of Tvalue)(ByRef obj As T, Name As String, value As Tvalue) As T
169             Dim type As Type = GetType(T)
170             Dim lstProp As PropertyInfo() =
171                 type.GetProperties(BindingFlags.Public Or BindingFlags.Instance)
172             Dim p As PropertyInfo =
173                 LinqAPI.DefaultFirst(Of PropertyInfo) <=
174                     From pInfo As PropertyInfo
175                     In lstProp
176                     Where String.Equals(Name, pInfo.Name)
177                     Select pInfo
178
179             If Not p Is Nothing Then
180                 Call p.SetValue(obj, value, Nothing)
181             Else
182                 Dim lstName As String =
183                     String.Join("; ", LinqAPI.Exec(Of String) <= From pp As PropertyInfo
184                                                                  In lstProp
185                                                                  Select ss =
186                                                                      pp.Name)
187                 VBDebugger.Warning($"Could Not found the target parameter which is named {Name} // {lstName}")
188             End If
189
190             Return obj
191         End Function
192
193         Public Iterator Function GetEnumerator() As IEnumerator(Of PropertyInfo) Implements IEnumerable(Of PropertyInfo).GetEnumerator
194             For Each x In __props.Values
195                 Yield x
196             Next
197         End Function
198
199         Private Iterator Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
200             Yield GetEnumerator()
201         End Function
202     End Class
203 End Namespace