using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Threading; using AspClassic.Scripting.Utils; namespace AspClassic.Scripting.Hosting; [Serializable] public sealed class LanguageSetup { private string _typeName; private string _displayName; private IList _names; private IList _fileExtensions; private IDictionary _options; private bool _frozen; private bool? _interpretedMode; private bool? _exceptionDetail; private bool? _perfStats; private bool? _noAdaptiveCompilation; public string TypeName { get { return _typeName; } set { ContractUtils.RequiresNotEmpty(value, "value"); CheckFrozen(); _typeName = value; } } public string DisplayName { get { return _displayName; } set { ContractUtils.RequiresNotNull(value, "value"); CheckFrozen(); _displayName = value; } } public IList Names => _names; public IList FileExtensions => _fileExtensions; public IDictionary Options => _options; [Obsolete("This option is ignored")] public bool InterpretedMode { get { return GetCachedOption("InterpretedMode", ref _interpretedMode); } set { CheckFrozen(); Options["InterpretedMode"] = value; } } [Obsolete("Use Options[\"NoAdaptiveCompilation\"] instead.")] public bool NoAdaptiveCompilation { get { return GetCachedOption("NoAdaptiveCompilation", ref _noAdaptiveCompilation); } set { CheckFrozen(); Options["NoAdaptiveCompilation"] = value; } } public bool ExceptionDetail { get { return GetCachedOption("ExceptionDetail", ref _exceptionDetail); } set { CheckFrozen(); Options["ExceptionDetail"] = value; } } [Obsolete("Use Options[\"PerfStats\"] instead.")] public bool PerfStats { get { return GetCachedOption("PerfStats", ref _perfStats); } set { CheckFrozen(); Options["PerfStats"] = value; } } public LanguageSetup(string typeName) : this(typeName, "", ArrayUtils.EmptyStrings, ArrayUtils.EmptyStrings) { } public LanguageSetup(string typeName, string displayName) : this(typeName, displayName, ArrayUtils.EmptyStrings, ArrayUtils.EmptyStrings) { } public LanguageSetup(string typeName, string displayName, IEnumerable names, IEnumerable fileExtensions) { ContractUtils.RequiresNotEmpty(typeName, "typeName"); ContractUtils.RequiresNotNull(displayName, "displayName"); ContractUtils.RequiresNotNull(names, "names"); ContractUtils.RequiresNotNull(fileExtensions, "fileExtensions"); _typeName = typeName; _displayName = displayName; _names = new List(names); _fileExtensions = new List(fileExtensions); _options = new Dictionary(); } public T GetOption(string name, T defaultValue) { if (_options != null && _options.TryGetValue(name, out var value)) { if (value is T) { return (T)value; } return (T)Convert.ChangeType(value, typeof(T), Thread.CurrentThread.CurrentCulture); } return defaultValue; } private bool GetCachedOption(string name, ref bool? storage) { if (storage.HasValue) { return storage.Value; } if (_frozen) { storage = GetOption(name, defaultValue: false); return storage.Value; } return GetOption(name, defaultValue: false); } internal void Freeze() { _frozen = true; _names = new ReadOnlyCollection(ArrayUtils.MakeArray(_names)); _fileExtensions = new ReadOnlyCollection(ArrayUtils.MakeArray(_fileExtensions)); _options = new AspClassic.Scripting.Utils.ReadOnlyDictionary(new Dictionary(_options)); } private void CheckFrozen() { if (_frozen) { throw new InvalidOperationException("Cannot modify LanguageSetup after it has been used to create a ScriptRuntime"); } } }