Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
NamedMember.cs
1using System;
2using System.Reflection;
3using System.Runtime.ExceptionServices;
4using System.Threading;
5using System.Threading.Tasks;
14
16{
21 {
22 private readonly string name;
23
35 {
36 this.name = Name;
37 this.isAsync = true;
38 }
39
43 public string Name => this.name;
44
49 public override bool IsAsynchronous => true;
50
58 {
59 return this.EvaluateAsync(Operand, Variables).Result;
60 }
61
68 public override async Task<IElement> EvaluateAsync(IElement Operand, Variables Variables)
69 {
70 object Value = Operand.AssociatedObjectValue;
71 object Instance;
72
73 if (Value is null && this.nullCheck)
74 return ObjectValue.Null;
75
76 Type T;
77
78 T = Value as Type;
79 if (T is null)
80 {
81 Instance = Value;
82 T = Value?.GetType() ?? typeof(object);
83 }
84 else
85 Instance = null;
86
87 await this.synchObject.WaitAsync();
88 try
89 {
90 if (T != this.type)
91 {
92 this.type = T;
93 this.field = null;
94 this._event = null;
95 this.methods = null;
96 this.nameIndex = null;
97 this.property = T.GetRuntimeProperty(this.name);
98
99 if (this.property is null)
100 {
101 this.field = T.GetRuntimeField(this.name);
102 if (this.field is null)
103 {
104 this._event = T.GetRuntimeEvent(this.name);
105 if (this._event is null)
106 {
108
109 foreach (MethodInfo MI in T.GetRuntimeMethods())
110 {
111 if (!MI.IsAbstract && MI.IsPublic && MI.Name == this.name)
112 {
113 if (Methods is null)
115
116 Methods.Add(new MethodLambda(Instance, MI));
117 }
118 }
119
120 this.methods = Methods?.ToArray();
121 if (this.methods is null)
122 {
123 if (VectorIndex.TryGetIndexProperty(T, true, false, out this.property,
124 out ParameterInfo[] IndexArguments) &&
125 (IndexArguments?.Length ?? 0) == 1)
126 {
127 if (IndexArguments[0].ParameterType == typeof(string))
128 this.nameIndex = new object[] { this.name };
129 else
130 this.nameIndex = new object[] { Expression.ConvertTo(this.name, IndexArguments[0].ParameterType, this) };
131 }
132 }
133 }
134 else
135 {
136 if (!this._event.AddMethod.IsPublic)
137 throw new ScriptRuntimeException("Event not accessible: " + this.name, this);
138 }
139 }
140 else
141 {
142 if (!this.field.IsPublic)
143 throw new ScriptRuntimeException("Field not accessible: " + this.name, this);
144 }
145 }
146 else
147 {
148 if (!this.property.CanRead)
149 throw new ScriptRuntimeException("Property cannot be read: " + this.name, this);
150 else if (!this.property.GetMethod.IsPublic)
151 throw new ScriptRuntimeException("Property not accessible: " + this.name, this);
152 }
153 }
154
155 object Result = null;
156
157 if (!(this.property is null))
158 {
159 try
160 {
161 Result = await WaitPossibleTask(this.property.GetValue(Instance, this.nameIndex));
162 }
163 catch (Exception ex)
164 {
165 if (Instance is null)
166 Result = this.property;
167 else
168 ExceptionDispatchInfo.Capture(ex).Throw();
169 }
170
171 return Expression.Encapsulate(Result);
172 }
173 else if (!(this.field is null))
174 {
175 try
176 {
177 Result = await WaitPossibleTask(this.field.GetValue(Instance));
178 }
179 catch (Exception ex)
180 {
181 if (Instance is null)
182 Result = this.field;
183 else
184 ExceptionDispatchInfo.Capture(ex).Throw();
185 }
186
187 return Expression.Encapsulate(Result);
188 }
189 else if (!(this._event is null))
190 return Expression.Encapsulate(this._event);
191 else if (!(this.methods is null))
192 {
193 if (this.methods.Length == 1)
194 return Expression.Encapsulate(this.methods[0]);
195 else
196 return Expression.Encapsulate(this.methods);
197 }
198 else if (Operand.IsScalar)
199 throw new ScriptRuntimeException("Member '" + this.name + "' not found on type '" + T.FullName + "'.", this);
200 }
201 finally
202 {
203 this.synchObject.Release();
204 }
205
207
208 foreach (IElement E in Operand.ChildElements)
209 Elements.Add(await EvaluateDynamic(E, this.name, this.nullCheck, this));
210
211 return Operand.Encapsulate(Elements, this);
212 }
213
214 private Type type = null;
215 private PropertyInfo property = null;
216 private FieldInfo field = null;
217 private EventInfo _event = null;
218 private MethodLambda[] methods = null;
219 private object[] nameIndex = null;
220 private readonly SemaphoreSlim synchObject = new SemaphoreSlim(1);
221
222 internal static readonly Type[] stringType = new Type[] { typeof(string) };
223
232 public static async Task<IElement> EvaluateDynamic(IElement Operand, string Name, bool NullCheck, ScriptNode Node)
233 {
234 object Value = Operand.AssociatedObjectValue;
235 object Instance;
236 Type T;
237
238 if (Value is null && NullCheck)
239 return ObjectValue.Null;
240
241 T = Value as Type;
242 if (T is null)
243 {
244 Instance = Value;
245 T = Value.GetType();
246 }
247 else
248 Instance = null;
249
250 PropertyInfo Property = T.GetRuntimeProperty(Name);
251 if (!(Property is null))
252 {
253 if (!Property.CanRead)
254 throw new ScriptRuntimeException("Property cannot be read: " + Name, Node);
255 else if (!Property.GetMethod.IsPublic)
256 throw new ScriptRuntimeException("Property not accessible: " + Name, Node);
257 else
258 return Expression.Encapsulate(await WaitPossibleTask(Property.GetValue(Instance, null)));
259 }
260
261 FieldInfo Field = T.GetRuntimeField(Name);
262 if (!(Field is null))
263 {
264 if (!Field.IsPublic)
265 throw new ScriptRuntimeException("Field not accessible: " + Name, Node);
266 else
267 return Expression.Encapsulate(await WaitPossibleTask(Field.GetValue(Instance)));
268 }
269
270 EventInfo Event = T.GetRuntimeEvent(Name);
271 if (!(Event is null))
272 return Expression.Encapsulate(Event);
273
275
276 foreach (MethodInfo MI in T.GetRuntimeMethods())
277 {
278 if (!MI.IsAbstract && MI.IsPublic && MI.Name == Name)
279 {
280 if (Methods is null)
282
283 Methods.Add(new MethodLambda(Instance, MI));
284 }
285 }
286
287 if (!(Methods is null))
288 {
289 if (Methods.Count == 1)
290 return Expression.Encapsulate(Methods[0]);
291 else
292 return Expression.Encapsulate(Methods.ToArray());
293 }
294
295 if (VectorIndex.TryGetIndexProperty(T, true, false, out Property,
296 out ParameterInfo[] IndexArguments) &&
297 (IndexArguments?.Length ?? 0) == 1)
298 {
299 object[] Index;
300
301 if (IndexArguments[0].ParameterType == typeof(string))
302 Index = new object[] { Name };
303 else
304 Index = new object[] { Expression.ConvertTo(Name, IndexArguments[0].ParameterType, Node) };
305
306 return Expression.Encapsulate(await WaitPossibleTask(Property.GetValue(Instance, Index)));
307 }
308
309 if (Operand.IsScalar)
310 throw new ScriptRuntimeException("Member '" + Name + "' not found on type '" + T.FullName + "'.", Node);
311
313
314 foreach (IElement E in Operand.ChildElements)
315 Elements.Add(await EvaluateDynamic(E, Name, NullCheck, Node));
316
317 return Operand.Encapsulate(Elements, Node);
318 }
319 }
320}
A chunked list is a linked list of chunks of objects of type T .
Definition: ChunkedList.cs:54
Euler's number.
Definition: E.cs:12
Class managing a script expression.
Definition: Expression.cs:41
static IElement Encapsulate(object Value)
Encapsulates an object.
Definition: Expression.cs:5241
static object ConvertTo(IElement Value, Type DesiredType, ScriptNode Node)
Tries to conevert an element value to a desired type.
Definition: Expression.cs:5385
Lambda expression executing object methods.
Definition: MethodLambda.cs:13
Extract the methods of a type or an object.
Definition: Methods.cs:18
Base class for all unary operators performing operand null checks.
bool NullCheck
If null check is to be used.
readonly bool nullCheck
If null should be returned if operand is null.
Base class for all nodes in a parsed script tree.
Definition: ScriptNode.cs:69
int Length
Length of expression covered by node.
Definition: ScriptNode.cs:101
static async Task< object > WaitPossibleTask(object Result)
Waits for any asynchronous process to terminate.
Definition: ScriptNode.cs:441
int Start
Start position in script expression.
Definition: ScriptNode.cs:92
static readonly ObjectValue Null
Null value.
Definition: ObjectValue.cs:88
override IElement Evaluate(IElement Operand, Variables Variables)
Evaluates the node, using the variables provided in the Variables collection.
Definition: NamedMember.cs:57
override async Task< IElement > EvaluateAsync(IElement Operand, Variables Variables)
Evaluates the node, using the variables provided in the Variables collection.
Definition: NamedMember.cs:68
override bool IsAsynchronous
If the node (or its decendants) include asynchronous evaluation. Asynchronous nodes should be evaluat...
Definition: NamedMember.cs:49
NamedMember(ScriptNode Operand, string Name, bool NullCheck, int Start, int Length, Expression Expression)
Named member operator
Definition: NamedMember.cs:33
static async Task< IElement > EvaluateDynamic(IElement Operand, string Name, bool NullCheck, ScriptNode Node)
Evaluates the member operator dynamically on an operand.
Definition: NamedMember.cs:232
static bool TryGetIndexProperty(Type T, bool ForReading, bool ForWriting, out PropertyInfo PropertyInfo, out ParameterInfo[] Parameters)
Tries to get a one-dimensional index property of a Type.
Definition: VectorIndex.cs:138
Collection of variables.
Definition: Variables.cs:25
Basic interface for all types of elements.
Definition: IElement.cs:21