/
EvilBeaver
/
OneScript
Обзор
Документация
Войти
/
EvilBeaver
/
OneScript
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
v2.0.2
src/OneScript.StandardLibrary/Collections/StructureImpl.cs
286 строк
9 KB
EvilBeaver
Возможность регистрировать свойства с заданным определением
29 окт 2025, 15:06
29 окт 2025, 15:06
e4b7c8b
Код
Авторство
О чём код?
/*---------------------------------------------------------- This Source Code Form is subject to the terms of the Mozilla Public License, v.2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ using System.Collections.Generic; using OneScript.Commons; using OneScript.Contexts; using OneScript.Exceptions; using OneScript.Execution; using OneScript.Types; using OneScript.Values; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; using ScriptEngine.Types; namespace OneScript.StandardLibrary.Collections { /// <summary> /// Универсальный объект, хранящий значения по именам свойств. /// Доступ к элементам структуры возможен через точку, или по имени свойства в квадратных скобках [] /// /// Возможен обход в цикле <c>Для Каждого Из</c>. При обходе, элементами коллекции являются объекты типа <see cref="KeyAndValueImpl">КлючИЗначение</see> /// </summary> /// <example> /// Пользователь = Новый Структура("Логин, Адрес, Пароль"); /// Пользователь.Логин = "user"; /// Пользователь.Адрес = "somemail@server.com"; /// Пользователь.Пароль = "password"; /// </example> /// <seealso cref="KeyAndValueImpl"/> [ContextClass("Структура", "Structure")] public class StructureImpl : DynamicPropertiesAccessor, ICollectionContext<KeyAndValueImpl>, IDebugPresentationAcceptor { private readonly List<IValue> _values = new List<IValue>(); private static readonly ContextMethodsMapper<StructureImpl> _methods = new ContextMethodsMapper<StructureImpl>(); private static readonly TypeDescriptor typeDescriptor = typeof(StructureImpl).GetTypeFromClassMarkup(); public StructureImpl() { DefineType(typeDescriptor); } public StructureImpl(string strProperties, params IValue[] values) { var nprop = 0; foreach (var item in strProperties.Split(',')) { var prop = item.Trim(); if (prop.Equals(string.Empty)) continue; Insert(prop, nprop < values.Length ? values[nprop] : null); ++nprop; } } public StructureImpl(FixedStructureImpl structure) { foreach (KeyAndValueImpl keyValue in structure) { Insert(keyValue.Key.ToString(), keyValue.Value); } } [ContextMethod("Вставить")] public void Insert(string name, IValue val = null) { if (!Utils.IsValidIdentifier(name)) throw InvalidPropertyNameException(name); var num = RegisterProperty(name); if (num == _values.Count) { _values.Add(null); } if (val == null) { val = ValueFactory.Create(); } SetPropValue(num, val); } [ContextMethod("Удалить", "Delete")] public void Remove(string name) { if (!Utils.IsValidIdentifier(name)) throw InvalidPropertyNameException(name); int propIndex; try { propIndex = GetPropertyNumber(name); } catch (PropertyAccessException) { return; } _values.RemoveAt(propIndex); RemoveProperty(name); } [ContextMethod("Свойство", "Property")] public bool HasProperty(string name, [ByRef] IVariable value = null) { if (!Utils.IsValidIdentifier(name)) throw InvalidPropertyNameException(name); int propIndex; try { propIndex = GetPropertyNumber(name); } catch (PropertyAccessException) { if(value != null) value.Value = ValueFactory.Create(); return false; } if(value != null) value.Value = GetPropValue(propIndex); return true; } public override IValue GetPropValue(int propNum) { return _values[propNum]; } public override void SetPropValue(int propNum, IValue newVal) { _values[propNum] = newVal; } public override int GetPropCount() { return _values.Count; } public override string GetPropName(int propNum) { return GetPropertyName(propNum); } public override BslMethodInfo GetMethodInfo(int methodNumber) { return _methods.GetRuntimeMethod(methodNumber); } public override void CallAsProcedure(int methodNumber, IValue[] arguments, IBslProcess process) { var binding = _methods.GetCallableDelegate(methodNumber); try { binding(this, arguments, process); } catch (System.Reflection.TargetInvocationException e) { throw e.InnerException; } } public override void CallAsFunction(int methodNumber, IValue[] arguments, out IValue retValue, IBslProcess process) { var binding = _methods.GetCallableDelegate(methodNumber); try { retValue = binding(this, arguments, process); } catch (System.Reflection.TargetInvocationException e) { throw e.InnerException; } } public override int GetMethodNumber(string name) { return _methods.FindMethod(name); } #region IReflectableContext Members public override int GetMethodsCount() { return _methods.Count; } #endregion #region ICollectionContext Members [ContextMethod("Количество", "Count")] public int Count() { return _values.Count; } public int Count(IBslProcess process) => Count(); [ContextMethod("Очистить", "Clear")] public void Clear() { ClearProperties(); _values.Clear(); } #endregion #region IEnumerable<IValue> Members public IEnumerator<KeyAndValueImpl> GetEnumerator() { foreach (var item in GetDynamicProperties()) { yield return new KeyAndValueImpl( ValueFactory.Create(item.Key), GetPropValue(item.Value)); } } #endregion #region IEnumerable Members System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } #endregion [ScriptConstructor] public static StructureImpl Constructor() { return new StructureImpl(); } /// <summary> /// Создает структуру по фиксированной структуре /// </summary> /// <param name="fixedStruct">Исходная структура</param> //[ScriptConstructor(Name = "Из фиксированной структуры")] private static StructureImpl Constructor(FixedStructureImpl fixedStruct) { return new StructureImpl(fixedStruct); } /// <summary> /// Создает структуру по заданному перечню свойств и значений /// </summary> /// <param name="param1">Фиксированная структура либо строка с именами свойств, указанными через запятую.</param> /// <param name="args">Только для перечня свойств: /// Значения свойств. Каждое значение передается, как отдельный параметр.</param> [ScriptConstructor(Name = "По ключам и значениям")] public static StructureImpl Constructor(IValue param1, IValue[] args) { return param1 switch { null => new StructureImpl(), BslStringValue s => new StructureImpl((string)s, args), FixedStructureImpl fixedstr => new StructureImpl(fixedstr), _ => throw new RuntimeException("В качестве параметра для конструктора можно передавать только ФиксированнаяСтруктура или Ключи и Значения") }; } private static RuntimeException InvalidPropertyNameException( string name ) { return new RuntimeException($"Задано неправильное имя атрибута структуры '{name}'"); } void IDebugPresentationAcceptor.Accept(IDebugValueVisitor visitor) { visitor.ShowProperties(this); } } }