예제 #1
0
        public static string MakeArray(
            [ExcelArgument(Description = "Name of the array object to create.")] string name,
            [ExcelArgument(Description = "Array of values.")] object[] values)
        {
            if (values == null || values.Length == 0)
            {
                throw new NNXException("Array cannot be empty.");
            }

            object       result;
            const string inconsistentArrayMessage = "Array must contain either only numbers or only strings. " +
                                                    "Encountered both in this array.";
            const string badTypeMessage = "Array elements must be either numbers or strings. Element" +
                                          " at position {0} was neither number nor string.";

            // Determine the type of the array. To do that,
            // find the first element that is neither null nor empty.
            var firstNonEmptyIndex = 0;

            while (firstNonEmptyIndex < values.Length && IsEmpty(values[firstNonEmptyIndex]))
            {
                firstNonEmptyIndex++;
            }

            if (firstNonEmptyIndex >= values.Length)
            {
                throw new NNXException("Array cannot be empty.");
            }

            var firstNonEmpty = values[firstNonEmptyIndex];

            if (firstNonEmpty is double)
            {
                var goodValues = new List <double>(values.Length - firstNonEmptyIndex);

                for (var i = 0; i < values.Length; i++)
                {
                    var value = values[i];

                    if (IsEmpty(value))
                    {
                        continue;
                    }

                    if (value is double)
                    {
                        goodValues.Add((double)value);
                        continue;
                    }

                    if (value is string)
                    {
                        throw new NNXException(inconsistentArrayMessage);
                    }

                    throw new NNXException(string.Format(badTypeMessage, i));
                }

                result = goodValues.ToArray();
            }
            else if (firstNonEmpty is string)
            {
                var goodValues = new List <string>(values.Length - firstNonEmptyIndex);

                for (var i = 0; i < values.Length; i++)
                {
                    var value = values[i];

                    if (IsEmpty(value))
                    {
                        continue;
                    }

                    if (value is string)
                    {
                        goodValues.Add((string)value);
                        continue;
                    }

                    if (value is double)
                    {
                        throw new NNXException(inconsistentArrayMessage);
                    }

                    throw new NNXException(string.Format(badTypeMessage, i));
                }

                result = goodValues.ToArray();
            }
            else
            {
                throw new NNXException(string.Format(badTypeMessage, 0));
            }

            ObjectStore.Add(name, result);
            return(name);
        }
예제 #2
0
 public static string ClearAllObjects()
 {
     ObjectStore.Clear();
     return("OK");
 }
예제 #3
0
        //[ExcelFunction(Name = "nnMakeObject")]
        public static string MakeObject(string name, string typeName, object[,] properties)
        {
            if (string.IsNullOrEmpty(typeName))
            {
                throw new NNXException("Argument TypeName should not be null or empty.");
            }

            Type objectType;

            if (!SupportedObjects.TryGetValue(typeName, out objectType))
            {
                throw new NNXException($"Unrecognized object type: '{typeName}'.");
            }

            var obj = Activator.CreateInstance(objectType);

            if (properties == null || properties.GetLength(0) == 0)
            {
                // No properties to set, we're done here.
                ObjectStore.Add(name, obj);
                return(name);
            }

            if (properties.GetLength(1) != 2)
            {
                throw new NNXException($"Argument Properties must have width 2; was: {properties.GetLength(1)}.");
            }

            var numProperties    = properties.GetLength(0);
            var objectProperties = objectType.GetProperties(BindingFlags.Instance | BindingFlags.Public)
                                   .Where(p => p.CanWrite).ToList();

            for (var i = 0; i < numProperties; i++)
            {
                var propertyName = properties[i, 0].ToString();
                var value        = properties[i, 1];

                if (string.IsNullOrEmpty(propertyName))
                {
                    throw new NNXException($"Property at position {i + 1} was empty.");
                }

                var targetProperty = objectProperties.FirstOrDefault(p => p.Name == propertyName);

                if (targetProperty == null)
                {
                    throw new NNXException($"Object type {typeName} does not have property {propertyName}.");
                }

                var propertyType = targetProperty.PropertyType;

                // Special case: assigning an integer double to int.
                if (propertyType == typeof(int) &&
                    value is double &&
                    (((double)value) % 1 == 0.0))
                {
                    targetProperty.SetValue(obj, (int)((double)value));
                    continue;
                }

                // Special case: assigning int to double.
                if (propertyType == typeof(double) && value is int)
                {
                    targetProperty.SetValue(obj, (double)((int)value));
                    continue;
                }

                // Special case: string.
                if (propertyType == typeof(string))
                {
                    var stringValue = value?.ToString() ?? "";
                    targetProperty.SetValue(obj, stringValue);
                    continue;
                }

                // General case.
                if (propertyType.IsInstanceOfType(value))
                {
                    targetProperty.SetValue(obj, value);
                    continue;
                }

                // If this was a simple type, then the user provided a value
                // of the wrong type.
                if (propertyType.IsAssignableFrom(typeof(int)) ||
                    propertyType.IsAssignableFrom(typeof(double)) ||
                    propertyType.IsAssignableFrom(typeof(string)))
                {
                    var propertyTypeName = MapPropertyType(propertyType);
                    var aOrAn            = AOrAn(propertyTypeName);

                    throw new NNXException($"Property {propertyName} of object type {typeName} " +
                                           $"must be {aOrAn} {propertyTypeName}; was {value}.");
                }

                // If we get here, then the target property is an array or array of arrays.
                var referencedName = properties[i, 1].ToString();

                // Special case: weights.
                if (propertyType.IsAssignableFrom(typeof(double[][])))
                {
                    double[][] weights;

                    if (!ObjectStore.TryGet(referencedName, out weights))
                    {
                        throw new NNXException($"Property {propertyName} of type {typeName} must be of type " +
                                               "Weights created using nnMakeWeights() function.");
                    }

                    targetProperty.SetValue(obj, weights);
                    continue;
                }

                // Special case: enumerables.
                if (propertyType.IsAssignableFrom(typeof(string[])))
                {
                    string[] array;

                    if (!ObjectStore.TryGet(referencedName, out array))
                    {
                        throw new NNXException($"Property {propertyName} of type {typeName} must refer " +
                                               $"to array containing elements of type string.");
                    }

                    targetProperty.SetValue(obj, array);
                    continue;
                }

                if (propertyType.IsAssignableFrom(typeof(double[])))
                {
                    double[] array;

                    if (!ObjectStore.TryGet(referencedName, out array))
                    {
                        throw new NNXException($"Property {propertyName} of type {typeName} must refer " +
                                               $"to array containing elements of type number.");
                    }

                    targetProperty.SetValue(obj, array);
                    continue;
                }

                if (propertyType.IsAssignableFrom(typeof(int[])))
                {
                    int[] intArray;

                    if (ObjectStore.TryGet(referencedName, out intArray))
                    {
                        targetProperty.SetValue(obj, intArray);
                        continue;
                    }

                    double[] doubleArray;

                    if (ObjectStore.TryGet(referencedName, out doubleArray))
                    {
                        var convertedArray = new int[doubleArray.Length];

                        for (var j = 0; j < doubleArray.Length; j++)
                        {
                            var doubleValue = doubleArray[j];

                            if (doubleValue % 1 != 0)
                            {
                                throw new NNXException($"Property {propertyName} of type {typeName} must refer " +
                                                       $"to array containing elements of type integer.");
                            }

                            convertedArray[j] = (int)doubleValue;
                        }

                        targetProperty.SetValue(obj, convertedArray);
                        continue;
                    }


                    throw new NNXException($"Property {propertyName} of type {typeName} must refer " +
                                           $"to array containing elements of type integer.");
                }

                throw new Exception("Reached unreacheable code.");
            }

            ObjectStore.Add(name, obj);
            return(name);
        }