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.Collections.Generic;
4using System.Runtime.ExceptionServices;
5using System.Threading.Tasks;
12using System.Threading;
13
15{
20 {
21 private readonly string name;
22
34 {
35 this.name = Name;
36 this.isAsync = true;
37 }
38
42 public string Name => this.name;
43
48 public override bool IsAsynchronous => true;
49
57 {
58 return this.EvaluateAsync(Operand, Variables).Result;
59 }
60
67 public override async Task<IElement> EvaluateAsync(IElement Operand, Variables Variables)
68 {
69 object Value = Operand.AssociatedObjectValue;
70 object Instance;
71
72 if (Value is null && this.nullCheck)
73 return ObjectValue.Null;
74
75 Type T;
76
77 T = Value as Type;
78 if (T is null)
79 {
80 Instance = Value;
81 T = Value?.GetType() ?? typeof(object);
82 }
83 else
84 Instance = null;
85
86 await this.synchObject.WaitAsync();
87 try
88 {
89 if (T != this.type)
90 {
91 this.type = T;
92 this.field = null;
93 this._event = null;
94 this.methods = null;
95 this.nameIndex = null;
96 this.property = T.GetRuntimeProperty(this.name);
97
98 if (this.property is null)
99 {
100 this.field = T.GetRuntimeField(this.name);
101 if (this.field is null)
102 {
103 this._event = T.GetRuntimeEvent(this.name);
104 if (this._event is null)
105 {
106 List<MethodLambda> Methods = null;
107
108 foreach (MethodInfo MI in T.GetRuntimeMethods())
109 {
110 if (!MI.IsAbstract && MI.IsPublic && MI.Name == this.name)
111 {
112 if (Methods is null)
113 Methods = new List<MethodLambda>();
114
115 Methods.Add(new MethodLambda(Instance, MI));
116 }
117 }
118
119 this.methods = Methods?.ToArray();
120 if (this.methods is null)
121 {
122 if (VectorIndex.TryGetIndexProperty(T, true, false, out this.property, out _))
123 this.nameIndex = new string[] { this.name };
124 }
125 }
126 else
127 {
128 if (!this._event.AddMethod.IsPublic)
129 throw new ScriptRuntimeException("Event not accessible: " + this.name, this);
130 }
131 }
132 else
133 {
134 if (!this.field.IsPublic)
135 throw new ScriptRuntimeException("Field not accessible: " + this.name, this);
136 }
137 }
138 else
139 {
140 if (!this.property.CanRead)
141 throw new ScriptRuntimeException("Property cannot be read: " + this.name, this);
142 else if (!this.property.GetMethod.IsPublic)
143 throw new ScriptRuntimeException("Property not accessible: " + this.name, this);
144 }
145 }
146
147 object Result = null;
148
149 if (!(this.property is null))
150 {
151 try
152 {
153 if (!(this.nameIndex is null))
154 Result = await WaitPossibleTask(this.property.GetValue(Instance, this.nameIndex));
155 else
156 Result = await WaitPossibleTask(this.property.GetValue(Instance, null));
157 }
158 catch (Exception ex)
159 {
160 if (Instance is null)
161 Result = this.property;
162 else
163 ExceptionDispatchInfo.Capture(ex).Throw();
164 }
165
166 return Expression.Encapsulate(Result);
167 }
168 else if (!(this.field is null))
169 {
170 try
171 {
172 Result = await WaitPossibleTask(this.field.GetValue(Instance));
173 }
174 catch (Exception ex)
175 {
176 if (Instance is null)
177 Result = this.field;
178 else
179 ExceptionDispatchInfo.Capture(ex).Throw();
180 }
181
182 return Expression.Encapsulate(Result);
183 }
184 else if (!(this._event is null))
185 return Expression.Encapsulate(this._event);
186 else if (!(this.methods is null))
187 {
188 if (this.methods.Length == 1)
189 return Expression.Encapsulate(this.methods[0]);
190 else
191 return Expression.Encapsulate(this.methods);
192 }
193 else if (Operand.IsScalar)
194 throw new ScriptRuntimeException("Member '" + this.name + "' not found on type '" + T.FullName + "'.", this);
195 }
196 finally
197 {
198 this.synchObject.Release();
199 }
200
201 LinkedList<IElement> Elements = new LinkedList<IElement>();
202
203 foreach (IElement E in Operand.ChildElements)
204 Elements.AddLast(await EvaluateDynamic(E, this.name, this.nullCheck, this));
205
206 return Operand.Encapsulate(Elements, this);
207 }
208
209 private Type type = null;
210 private PropertyInfo property = null;
211 private FieldInfo field = null;
212 private EventInfo _event = null;
213 private MethodLambda[] methods = null;
214 private string[] nameIndex = null;
215 private readonly SemaphoreSlim synchObject = new SemaphoreSlim(1);
216
217 internal static readonly Type[] stringType = new Type[] { typeof(string) };
218
227 public static async Task<IElement> EvaluateDynamic(IElement Operand, string Name, bool NullCheck, ScriptNode Node)
228 {
229 object Value = Operand.AssociatedObjectValue;
230 object Instance;
231 Type T;
232
233 if (Value is null && NullCheck)
234 return ObjectValue.Null;
235
236 T = Value as Type;
237 if (T is null)
238 {
239 Instance = Value;
240 T = Value.GetType();
241 }
242 else
243 Instance = null;
244
245 PropertyInfo Property = T.GetRuntimeProperty(Name);
246 if (!(Property is null))
247 {
248 if (!Property.CanRead)
249 throw new ScriptRuntimeException("Property cannot be read: " + Name, Node);
250 else if (!Property.GetMethod.IsPublic)
251 throw new ScriptRuntimeException("Property not accessible: " + Name, Node);
252 else
253 return Expression.Encapsulate(await WaitPossibleTask(Property.GetValue(Instance, null)));
254 }
255
256 FieldInfo Field = T.GetRuntimeField(Name);
257 if (!(Field is null))
258 {
259 if (!Field.IsPublic)
260 throw new ScriptRuntimeException("Field not accessible: " + Name, Node);
261 else
262 return Expression.Encapsulate(await WaitPossibleTask(Field.GetValue(Instance)));
263 }
264
265 EventInfo Event = T.GetRuntimeEvent(Name);
266 if (!(Event is null))
267 return Expression.Encapsulate(Event);
268
269 List<MethodLambda> Methods = null;
270
271 foreach (MethodInfo MI in T.GetRuntimeMethods())
272 {
273 if (!MI.IsAbstract && MI.IsPublic && MI.Name == Name)
274 {
275 if (Methods is null)
276 Methods = new List<MethodLambda>();
277
278 Methods.Add(new MethodLambda(Instance, MI));
279 }
280 }
281
282 if (!(Methods is null))
283 {
284 if (Methods.Count == 1)
285 return Expression.Encapsulate(Methods[0]);
286 else
287 return Expression.Encapsulate(Methods.ToArray());
288 }
289
290 if (VectorIndex.TryGetIndexProperty(T, true, false, out Property, out _))
291 return Expression.Encapsulate(await WaitPossibleTask(Property.GetValue(Instance, new string[] { Name })));
292
293 if (Operand.IsScalar)
294 throw new ScriptRuntimeException("Member '" + Name + "' not found on type '" + T.FullName + "'.", Node);
295
296 LinkedList<IElement> Elements = new LinkedList<IElement>();
297
298 foreach (IElement E in Operand.ChildElements)
299 Elements.AddLast(await EvaluateDynamic(E, Name, NullCheck, Node));
300
301 return Operand.Encapsulate(Elements, Node);
302 }
303 }
304}
Class managing a script expression.
Definition: Expression.cs:39
static IElement Encapsulate(object Value)
Encapsulates an object.
Definition: Expression.cs:4955
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:417
int Start
Start position in script expression.
Definition: ScriptNode.cs:92
static readonly ObjectValue Null
Null value.
Definition: ObjectValue.cs:86
override IElement Evaluate(IElement Operand, Variables Variables)
Evaluates the node, using the variables provided in the Variables collection.
Definition: NamedMember.cs:56
override async Task< IElement > EvaluateAsync(IElement Operand, Variables Variables)
Evaluates the node, using the variables provided in the Variables collection.
Definition: NamedMember.cs:67
override bool IsAsynchronous
If the node (or its decendants) include asynchronous evaluation. Asynchronous nodes should be evaluat...
Definition: NamedMember.cs:48
NamedMember(ScriptNode Operand, string Name, bool NullCheck, int Start, int Length, Expression Expression)
Named member operator
Definition: NamedMember.cs:32
static async Task< IElement > EvaluateDynamic(IElement Operand, string Name, bool NullCheck, ScriptNode Node)
Evaluates the member operator dynamically on an operand.
Definition: NamedMember.cs:227
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:133
Collection of variables.
Definition: Variables.cs:25
Basic interface for all types of elements.
Definition: IElement.cs:20