コード例 #1
0
        private static (object value, string error) Evaluator(Expression expression, IMemory state, Options options)
        {
            object value = null;
            string error = null;
            IReadOnlyList <object> args;

            (args, error) = FunctionUtils.EvaluateChildren(expression, state, options);
            if (error == null)
            {
                if (args[0] is string uri)
                {
                    (value, error) = EvalUriQuery(uri);
                }
                else
                {
                    error = $"{expression} should contain a URI string.";
                }
            }

            return(value, error);
        }
コード例 #2
0
        private static (object value, string error) Evaluator(Expression expression, IMemory state, Options options)
        {
            object result;
            string error;

            (result, error) = expression.Children[0].TryEvaluate(state, new Options(options)
            {
                NullSubstitution = null
            });
            if (error == null && FunctionUtils.IsLogicTrue(result))
            {
                (result, error) = expression.Children[1].TryEvaluate(state, options);
            }
            else
            {
                // Swallow error and treat as false
                (result, error) = expression.Children[2].TryEvaluate(state, options);
            }

            return(result, error);
        }
コード例 #3
0
        private static (object, string) EvalUriQuery(string uri)
        {
            var(result, error) = FunctionUtils.ParseUri(uri);
            if (error == null)
            {
                try
                {
                    var uriBase = (Uri)result;
                    var query   = uriBase.Query;
                    result = query.ToString();
                }
#pragma warning disable CA1031 // Do not catch general exception types  (capture any exception and return generic error)
                catch
#pragma warning restore CA1031 // Do not catch general exception types
                {
                    error = "invalid operation, input uri should be an absolute URI";
                }
            }

            return(result, error);
        }
コード例 #4
0
        private static EvaluateExpressionDelegate Evaluator()
        {
            return(FunctionUtils.ApplyWithOptionsAndError(
                       (args, options) =>
            {
                string result = null;
                string error = null;
                var locale = options.Locale != null ? new CultureInfo(options.Locale) : Thread.CurrentThread.CurrentCulture;
                if (!args[0].IsNumber())
                {
                    error = $"formatNumber first argument {args[0]} must be number";
                }
                else if (!args[1].IsInteger())
                {
                    error = $"formatNumber second argument {args[1]} must be number";
                }
                else if (args.Count == 3 && !(args[2] is string))
                {
                    error = $"formatNumber third agument {args[2]} must be a locale";
                }

                if (error == null)
                {
                    (locale, error) = FunctionUtils.DetermineLocale(args, locale, 3);
                }

                if (error == null)
                {
                    var precision = 0;
                    (precision, error) = FunctionUtils.ParseInt32(args[1]);
                    if (error == null)
                    {
                        var number = Convert.ToDouble(args[0], CultureInfo.InvariantCulture);
                        result = number.ToString("N" + precision.ToString(CultureInfo.InvariantCulture), locale);
                    }
                }

                return (result, error);
            }));
        }
コード例 #5
0
        private static (object value, string error) Evaluator(Expression expression, IMemory state, Options options)
        {
            object value = null;
            string error;
            var    instance = expression.Children[0];
            var    index    = expression.Children[1];
            object inst;

            (inst, error) = instance.TryEvaluate(state, options);
            if (error == null)
            {
                object idxValue;
                (idxValue, error) = index.TryEvaluate(state, new Options(options)
                {
                    NullSubstitution = null
                });
                if (error == null)
                {
                    if (idxValue.IsInteger())
                    {
                        var idx = 0;
                        (idx, error) = FunctionUtils.ParseInt32(idxValue);
                        if (error == null)
                        {
                            (value, error) = FunctionUtils.AccessIndex(inst, idx);
                        }
                    }
                    else if (idxValue is string idxStr)
                    {
                        FunctionUtils.TryAccessProperty(inst, idxStr, out value);
                    }
                    else
                    {
                        error = $"Could not coerce {index}<{idxValue?.GetType()}> to an int or string";
                    }
                }
            }

            return(value, error);
        }
コード例 #6
0
ファイル: Flatten.cs プロジェクト: stantoxt/botbuilder-dotnet
        private static IEnumerable <object> EvalFlatten(IEnumerable <object> list, int dept)
        {
            var result = list.ToList();

            if (dept < 1)
            {
                dept = 1;
            }

            for (var i = 0; i < dept; i++)
            {
                var hasArray = result.Any(u => FunctionUtils.TryParseList(u, out var _));
                if (hasArray)
                {
                    var tempList = new List <object>();
                    foreach (var item in result)
                    {
                        if (FunctionUtils.TryParseList(item, out var itemList))
                        {
                            foreach (var childItem in itemList)
                            {
                                tempList.Add(childItem);
                            }
                        }
                        else
                        {
                            tempList.Add(item);
                        }
                    }

                    result = tempList.ToList();
                }
                else
                {
                    break;
                }
            }

            return(result);
        }
コード例 #7
0
        private static (List <JObject>, string) ParseToObjectList(object arg)
        {
            var    result = new List <JObject>();
            string error  = null;

            if (arg == null)
            {
                error = $"The argument {arg} must be a JSON object or array.";
            }
            else if (FunctionUtils.TryParseList(arg, out var array))
            {
                var jarray = JArray.FromObject(array);
                foreach (var jtoken in jarray)
                {
                    if (jtoken is JObject jobj)
                    {
                        result.Add(jobj);
                    }
                    else
                    {
                        error = $"The argument {jtoken} in array must be a JSON object.";
                        break;
                    }
                }
            }
            else
            {
                var jtoken = FunctionUtils.ConvertToJToken(arg);
                if (jtoken is JObject jobj)
                {
                    result.Add(jobj);
                }
                else
                {
                    error = $"The argument {arg} must be a JSON object or array.";
                }
            }

            return(result, error);
        }
コード例 #8
0
        private static EvaluateExpressionDelegate Evaluator()
        {
            return(FunctionUtils.ApplyWithOptionsAndError(
                       (args, options) =>
            {
                string error = null;
                string result = null;
                var locale = options.Locale != null ? new CultureInfo(options.Locale) : Thread.CurrentThread.CurrentCulture;
                if (error == null)
                {
                    (locale, error) = FunctionUtils.DetermineLocale(args, locale, 2);
                }

                if (error == null)
                {
                    if (args[0].IsNumber())
                    {
                        result = Convert.ToDouble(args[0], CultureInfo.InvariantCulture).ToString(locale);
                    }
                    else if (args[0] is DateTime dt)
                    {
                        result = dt.ToString(FunctionUtils.DefaultDateTimeFormat, locale);
                    }
                    else if (args[0] is string str)
                    {
                        result = str;
                    }
                    else if (args[0] is byte[] byteArr)
                    {
                        result = System.Text.Encoding.UTF8.GetString(byteArr);
                    }
                    else
                    {
                        result = JsonConvert.SerializeObject(args[0]).TrimStart('"').TrimEnd('"');
                    }
                }

                return (result, error);
            }));
        }
コード例 #9
0
        private static EvaluateExpressionDelegate Evaluator()
        {
            return(FunctionUtils.ApplyWithError(
                       args =>
            {
                object value = null;
                string error = null;
                (value, error) = FunctionUtils.NormalizeToDateTime(args[0]);
                if (error == null)
                {
                    var timestamp = (DateTime)value;
                    if (timestamp.Hour == 0 && timestamp.Minute == 0)
                    {
                        value = "midnight";
                    }
                    else if (timestamp.Hour >= 0 && timestamp.Hour < 12)
                    {
                        value = "morning";
                    }
                    else if (timestamp.Hour == 12 && timestamp.Minute == 0)
                    {
                        value = "noon";
                    }
                    else if (timestamp.Hour < 18)
                    {
                        value = "afternoon";
                    }
                    else if (timestamp.Hour < 22 || (timestamp.Hour == 22 && timestamp.Minute == 0))
                    {
                        value = "evening";
                    }
                    else
                    {
                        value = "night";
                    }
                }

                return (value, error);
            }));
        }
コード例 #10
0
        private static EvaluateExpressionDelegate Evaluator()
        {
            return(FunctionUtils.ApplyWithError(
                       args =>
            {
                string result = null;
                string error = null;
                if (!args[0].IsNumber())
                {
                    error = $"formatNumber first argument {args[0]} must be number";
                }
                else if (!args[1].IsInteger())
                {
                    error = $"formatNumber second argument {args[1]} must be number";
                }
                else if (args.Count == 3 && !(args[2] is string))
                {
                    error = $"formatNumber third agument {args[2]} must be a locale";
                }
                else
                {
                    var precision = 0;
                    (precision, error) = FunctionUtils.ParseInt32(args[1]);
                    try
                    {
                        var number = Convert.ToDouble(args[0], CultureInfo.InvariantCulture);
                        var locale = args.Count == 3 ? new CultureInfo(args[2] as string) : CultureInfo.InvariantCulture;
                        result = number.ToString("N" + precision, locale);
                    }
#pragma warning disable CA1031 // Do not catch general exception types (we are capturing the exception and returning it)
                    catch
#pragma warning restore CA1031 // Do not catch general exception types
                    {
                        error = $"{args[3]} is not a valid locale for formatNumber";
                    }
                }

                return (result, error);
            }));
        }
コード例 #11
0
        private static (object value, string error) Evaluator(Expression expression, IMemory state, Options options)
        {
            object value = null;
            string error = null;
            IReadOnlyList <object> args;

            (args, error) = FunctionUtils.EvaluateChildren(expression, state, options);
            if (error == null)
            {
                var format = (args.Count == 3) ? (string)args[2] : FunctionUtils.DefaultDateTimeFormat;
                if (args[1] is string targetTimeZone)
                {
                    (value, error) = EvalConvertFromUTC(args[0], targetTimeZone, format);
                }
                else
                {
                    error = $"{expression} should contain an ISO format timestamp, a destination time zone string and an optional output format string.";
                }
            }

            return(value, error);
        }
コード例 #12
0
        private JArray GetItemsProperty(Memory.DialogStateManager state, bool beginDialog)
        {
            var instance = state.GetValue <object>(this.ItemsProperty.GetValue(state));
            var result   = new JArray();

            if (FunctionUtils.TryParseList(instance, out var list))
            {
                for (var i = 0; i < list.Count; i++)
                {
                    result.Add(new JObject
                    {
                        [IterationKey]   = ConvertToJToken(i),
                        [IterationValue] = ConvertToJToken(list[i])
                    });
                }
            }
            else if (instance is JObject jobj)
            {
                result = Object2List(jobj);
            }
            else if (ConvertToJToken(instance) is JObject jobject)
            {
                result = Object2List(jobject);
            }

            if (beginDialog)
            {
                state.SetValue(CachedItemsProperty, result);
            }
            else if (result == null || result.Count == 0)
            {
                if (state.TryGetValue <JArray>(CachedItemsProperty, out JArray cached))
                {
                    result = cached;
                }
            }

            return(result);
        }
コード例 #13
0
        private static (object value, string error) Evaluator(Expression expression, IMemory state, Options options)
        {
            object value = null;
            string error = null;
            IReadOnlyList <object> args;

            (args, error) = FunctionUtils.EvaluateChildren(expression, state, options);
            if (error == null)
            {
                var format = (args.Count == 4) ? (string)args[3] : FunctionUtils.DefaultDateTimeFormat;
                if (args[1].IsInteger() && args[2] is string timeUnit)
                {
                    (value, error) = EvalAddToTime(args[0], Convert.ToInt64(args[1], CultureInfo.InvariantCulture), timeUnit, format);
                }
                else
                {
                    error = $"{expression} should contain an ISO format timestamp, a time interval integer, a string unit of time and an optional output format string.";
                }
            }

            return(value, error);
        }
コード例 #14
0
        private static (object value, string error) Evaluator(Expression expression, IMemory state, Options options)
        {
            var found = false;

            var(args, error) = FunctionUtils.EvaluateChildren(expression, state, options);
            if (error == null)
            {
                if (args[0] is string string0 && args[1] is string string1)
                {
                    found = string0.Contains(string1);
                }
                else if (FunctionUtils.TryParseList(args[0], out IList ilist))
                {
                    // list to find a value
                    var operands = FunctionUtils.ResolveListValue(ilist);
                    found = operands.Contains(args[1]);
                }
                else if (args[1] is string string2)
                {
                    found = FunctionUtils.TryAccessProperty((object)args[0], string2, out var _);
                }
            }
コード例 #15
0
        private void BuildReferencesNode(int level, ref bool passFiltering,
                                         ref TreeViewItem childNode, Node childLabel, bool showIcon)
        {
            if (childLabel.Get <ReferenceInterpreter>() != null && childLabel.Get <ReferenceInterpreter>().Node != null)
            {
                var referenceNode = childLabel.Get <ReferenceInterpreter>().Node;
                var functionName  = FunctionUtils.GetFunctionName(referenceNode);
                if (functionName == FunctionNames.SubShape)
                {
                    referenceNode = new NodeBuilder(referenceNode)[0].Reference;
                }
                if (BlockCircularReferences(childLabel, referenceNode))
                {
                    BuildReferencedChildNode(level, ref passFiltering, ref childNode, referenceNode, showIcon);
                }
            }

            if (childLabel.Get <ReferenceListInterpreter>() != null)
            {
                BuildReferencedListChildrenNodes(level, ref passFiltering, ref childNode, childLabel, showIcon);
            }
        }
コード例 #16
0
        private static (object, string) EvalUriHost(string uri)
        {
            var(result, error) = FunctionUtils.ParseUri(uri);

            if (error == null)
            {
                try
                {
                    var uriBase = (Uri)result;
                    var host    = uriBase.Host;
                    result = host.ToString();
                }
#pragma warning disable CA1031 // Do not catch general exception types (we are capturing the exception and returning a generic error for all failures)
                catch
#pragma warning restore CA1031 // Do not catch general exception types
                {
                    error = "invalid operation, input uri should be an absolute URI";
                }
            }

            return(result, error);
        }
コード例 #17
0
        private static (object, string) Function(IReadOnlyList <object> args, Options options)
        {
            string result = null;
            string error  = null;
            var    locale = options.Locale != null ? new CultureInfo(options.Locale) : Thread.CurrentThread.CurrentCulture;

            (locale, error) = FunctionUtils.DetermineLocale(args, locale, 2);

            if (error == null)
            {
                if (args[0] == null)
                {
                    result = string.Empty;
                }
                else
                {
                    result = args[0].ToString().ToUpper(locale);
                }
            }

            return(result, error);
        }
コード例 #18
0
        private static (object value, string error) Evaluator(Expression expression, IMemory state, Options options)
        {
            object value = null;
            string error = null;
            IReadOnlyList <object> args;
            var locale = options.Locale != null ? new CultureInfo(options.Locale) : Thread.CurrentThread.CurrentCulture;
            var format = FunctionUtils.DefaultDateTimeFormat;

            (args, error) = FunctionUtils.EvaluateChildren(expression, state, options);

            if (error == null)
            {
                (format, locale, error) = FunctionUtils.DetermineFormatAndLocale(args, format, locale, 3);
            }

            if (error == null)
            {
                (value, error) = StartOfHourWithError(args[0], format, locale);
            }

            return(value, error);
        }
コード例 #19
0
        private static EvaluateExpressionDelegate Evaluator(Func <DateTime, int, DateTime> function)
        {
            return((expression, state, options) =>
            {
                object value = null;
                string error = null;
                IReadOnlyList <object> args;
                (args, error) = FunctionUtils.EvaluateChildren(expression, state, options);
                if (error == null)
                {
                    if (args[1].IsInteger())
                    {
                        var formatString = (args.Count == 3 && args[2] is string string1) ? string1 : FunctionUtils.DefaultDateTimeFormat;
                        (value, error) = FunctionUtils.NormalizeToDateTime(args[0], dt =>
                        {
                            var result = dt;
                            var(interval, error) = FunctionUtils.ParseInt32(args[1]);
                            if (error == null)
                            {
                                result = function(dt, interval);
                            }

                            return (result, error);
                        });

                        if (error == null)
                        {
                            value = Convert.ToDateTime(value, CultureInfo.InvariantCulture).ToString(formatString, CultureInfo.InvariantCulture);
                        }
                    }
                    else
                    {
                        error = $"{expression} should contain an ISO format timestamp and a time interval integer.";
                    }
                }

                return (value, error);
            });
        }
コード例 #20
0
        //拷贝循环
        private void copycircle()
        {
            if (topathnum < topaths.Length)
            {
                totalSize = 0;
                position  = 0;
                topath    = topaths[topathnum];
                topath    = FunctionUtils.AutoCreateFolder(topath);
                if (topath != null)
                {
                    try {
                        var fs = new FileStream(frompath, FileMode.Open, FileAccess.Read);
                        totalSize = (int)fs.Length;
                        stream    = fs;
                    } catch (Exception) {
                        MessageBox.Show("读取文件失败:" + frompath, "提示");
                        return;
                    }

                    if (File.Exists(topaths[topathnum] + "/" + filename))
                    {
                        File.Delete(topaths[topathnum] + "/" + filename);
                    }
                    if (totalSize < BUFFER_SIZE)
                    {
                        BUFFER_SIZE = totalSize;
                    }
                    buffer = new byte[BUFFER_SIZE];
                    stream.BeginRead(buffer, 0, BUFFER_SIZE, new AsyncCallback(AsyncCopyFile), null);
                }
                else
                {
                    MessageBox.Show("文件路径不存在,尝试创建路径失败", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    topathnum++;
                    copycircle();
                }
            }
        }
コード例 #21
0
        public SolverGeometricObject ExtractGeometry(Node node)
        {
            if (!SolverGeometryExtracter.HasShapeOrInteractive(node))
            {
                return(null);
            }
            var functionName = FunctionUtils.GetFunctionName(node);

            if (string.IsNullOrEmpty(functionName))
            {
                return(null);
            }
            if (IsHidden(node))
            {
                return(null);
            }
            SolverGeometryExtracter extracter;
            var tryExtracter = GeometryExtracters.TryGetValue(functionName, out extracter);

            return(!tryExtracter
                       ? _genericExtracter.ExtractSolverGeometry(node)
                       : extracter.ExtractSolverGeometry(node));
        }
コード例 #22
0
        private static (object, string) Function(IReadOnlyList <object> args, Options options)
        {
            string result = null;
            string error  = null;
            var    locale = options.Locale != null ? new CultureInfo(options.Locale) : Thread.CurrentThread.CurrentCulture;

            (locale, error) = FunctionUtils.DetermineLocale(args, locale, 2);

            if (error == null)
            {
                var inputStr = (string)args[0];
                if (string.IsNullOrEmpty(inputStr))
                {
                    result = string.Empty;
                }
                else
                {
                    result = inputStr.Substring(0, 1).ToUpper(locale) + inputStr.Substring(1).ToLower(locale);
                }
            }

            return(result, error);
        }
コード例 #23
0
        private static EvaluateExpressionDelegate Evaluator()
        {
            return(FunctionUtils.ApplyWithError(
                       args =>
            {
                object result = null;
                string error;
                (result, error) = FunctionUtils.NormalizeToDateTime(args[0]);
                if (error == null)
                {
                    var timestamp1 = (DateTime)result;
                    (result, error) = FunctionUtils.NormalizeToDateTime(args[1]);
                    if (error == null)
                    {
                        var timestamp2 = (DateTime)result;
                        var timex = new TimexProperty(timestamp2.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture));
                        result = TimexRelativeConvert.ConvertTimexToStringRelative(timex, timestamp1);
                    }
                }

                return (result, error);
            }));
        }
コード例 #24
0
        private static bool IsEmpty(object instance)
        {
            bool result;

            if (instance == null)
            {
                result = true;
            }
            else if (instance is string string0)
            {
                result = string.IsNullOrEmpty(string0);
            }
            else if (FunctionUtils.TryParseList(instance, out var list))
            {
                result = list.Count == 0;
            }
            else
            {
                result = instance.GetType().GetProperties().Length == 0;
            }

            return(result);
        }
コード例 #25
0
        private static (object value, string error) Evaluator(Expression expression, IMemory state, Options options)
        {
            TimexProperty          parsed = null;
            bool?                  value  = null;
            string                 error  = null;
            IReadOnlyList <object> args;

            (args, error) = FunctionUtils.EvaluateChildren(expression, state, options);
            if (error == null)
            {
                (parsed, error) = FunctionUtils.ParseTimexProperty(args[0]);
            }

            if (error == null)
            {
                value = (parsed.Year != null && parsed.DayOfMonth == null) ||
                        (parsed.Year != null && parsed.Month != null && parsed.DayOfMonth == null) ||
                        (parsed.Month != null && parsed.DayOfMonth == null) ||
                        parsed.Season != null || parsed.WeekOfYear != null || parsed.WeekOfMonth != null;
            }

            return(value, error);
        }
コード例 #26
0
        private static EvaluateExpressionDelegate Evaluator()
        {
            return(FunctionUtils.ApplyWithError(
                       args =>
            {
                string error = null;
                string result = null;
                string inputStr = FunctionUtils.ParseStringOrNull(args[0]);
                string oldStr = FunctionUtils.ParseStringOrNull(args[1]);
                if (oldStr.Length == 0)
                {
                    error = $"{args[1]} the oldValue in replace function should be a string with at least length 1.";
                }

                string newStr = FunctionUtils.ParseStringOrNull(args[2]);
                if (error == null)
                {
                    result = inputStr.Replace(oldStr, newStr);
                }

                return (result, error);
            }, FunctionUtils.VerifyStringOrNull));
        }
コード例 #27
0
        protected override void PopulateExtendedView(StackPanel panel, SelectionContainer entity)
        {
            var node         = entity.Entities[0].Node;
            var functionName = FunctionUtils.GetFunctionName(node);
            var descriptor   = DescriptorsFactory.Instance.GetFunctionTab(functionName);

            descriptor.RefreshNode(panel, node, ViewInfo, new List <string>());
            ViewInfo.Document.Changed += OnDocumentChange;

            var gradient = new LinearGradientBrush
            {
                StartPoint    = new Point(0, 0),
                EndPoint      = new Point(0, 1),
                GradientStops = new GradientStopCollection
                {
                    new GradientStop(Colors.White, 0),
                    new GradientStop(Colors.DarkGray, 0.3),
                    new GradientStop(Colors.LightBlue, 1)
                }
            };

            panel.Background = gradient;
        }
コード例 #28
0
        private static (object value, string error) Evaluator(Expression expression, IMemory state, Options options)
        {
            object value = null;
            string error;
            object firstItem;
            object property;

            var children = expression.Children;

            (firstItem, error) = children[0].TryEvaluate(state, options);
            if (error == null)
            {
                if (children.Length == 1)
                {
                    // get root value from memory
                    if (!(firstItem is string))
                    {
                        error = $"Single parameter {children[0]} is not a string.";
                    }
                    else
                    {
                        (value, error) = FunctionUtils.WrapGetValue(state, (string)firstItem, options);
                    }
                }
                else
                {
                    // get the peoperty value from the instance
                    (property, error) = children[1].TryEvaluate(state, options);
                    if (error == null)
                    {
                        (value, error) = FunctionUtils.WrapGetValue(MemoryFactory.Create(firstItem), (string)property, options);
                    }
                }
            }

            return(value, error);
        }
コード例 #29
0
        private static bool Function(IReadOnlyList <object> args)
        {
            if (args[0] == null || args[1] == null)
            {
                // null will only equals to null
                return(args[0] == null && args[1] == null);
            }

            if (FunctionUtils.TryParseList(args[0], out IList l0) && l0.Count == 0 && (FunctionUtils.TryParseList(args[1], out IList l1) && l1.Count == 0))
            {
                return(true);
            }

            if (GetPropertyCount(args[0]) == 0 && GetPropertyCount(args[1]) == 0)
            {
                return(true);
            }

            if (args[0].IsNumber() && args[0].IsNumber())
            {
                if (Math.Abs(FunctionUtils.CultureInvariantDoubleConvert(args[0]) - FunctionUtils.CultureInvariantDoubleConvert(args[1])) < double.Epsilon)
                {
                    return(true);
                }
            }

            try
            {
                return(args[0] == args[1] || (args[0] != null && args[0].Equals(args[1])));
            }
#pragma warning disable CA1031 // Do not catch general exception types (we return false if it fails for whatever reason)
            catch
#pragma warning restore CA1031 // Do not catch general exception types
            {
                return(false);
            }
        }
コード例 #30
0
        private (object result, string error) SetProperty(object instance, string property, object value)
        {
            var    result = value;
            string error  = null;

            if (instance is IDictionary <string, object> idict)
            {
                idict[property] = value;
            }
            else if (instance is IDictionary dict)
            {
                dict[property] = value;
            }
            else if (instance is JObject jobj)
            {
                jobj[property] = FunctionUtils.ConvertToJToken(value);
            }
            else
            {
                // Use reflection
                var type = instance.GetType();
                var prop = type.GetProperties().Where(p => p.Name.ToLower() == property).SingleOrDefault();
                if (prop != null)
                {
                    if (prop.CanWrite)
                    {
                        prop.SetValue(instance, value);
                    }
                    else
                    {
                        error = $"property {prop.Name} is read-only";
                    }
                }
            }

            return(result, error);
        }