Ejemplo n.º 1
0
        /// <summary>
        /// Find all properties from the model and fill this.properties.
        /// </summary>
        public void FindAllProperties(Model model)
        {
            this.model = model;
            this.properties.Clear();
            if (this.model != null)
            {
                foreach (PropertyInfo property in this.model.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy))
                {
                    // Properties must have a [Description], not be called Name, and be read/write.
                    bool hasDescription = property.IsDefined(typeof(DescriptionAttribute), false);
                    bool includeProperty = hasDescription &&
                                           property.Name != "Name" &&
                                           property.CanRead &&
                                           property.CanWrite;

                    // Only allow lists that are double[], int[] or string[]
                    if (includeProperty && property.PropertyType.GetInterface("IList") != null)
                    {
                        includeProperty = property.PropertyType == typeof(double[]) ||
                                          property.PropertyType == typeof(int[]) ||
                                          property.PropertyType == typeof(string[]);
                    }

                    if (includeProperty)
                    {
                        this.properties.Add(new VariableProperty(this.model, property));
                    }

                    if (property.PropertyType == typeof(DataTable))
                    {
                        VariableProperty vp = new VariableProperty(this.model, property);
                        DataTable dt = vp.Value as DataTable;
                        this.grid.DataSource = dt;
                    }
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Set the value of the specified property
        /// </summary>
        /// <param name="property">The property to set the value of</param>
        /// <param name="value">The value to set the property to</param>
        private void SetPropertyValue(VariableProperty property, object value)
        {
            if (property.DataType.IsArray && value != null)
            {
                string[] stringValues = value.ToString().Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                if (property.DataType == typeof(double[]))
                {
                    value = MathUtilities.StringsToDoubles(stringValues);
                }
                else if (property.DataType == typeof(int[]))
                {
                    value = MathUtilities.StringsToDoubles(stringValues);
                }
                else if (property.DataType == typeof(string[]))
                {
                    value = stringValues;
                }
                else
                {
                    throw new ApsimXException(this.model, "Invalid property type: " + property.DataType.ToString());
                }
            }
            else if (typeof(ICrop).IsAssignableFrom(property.DataType))
            {
                value = Apsim.Find(this.model, value.ToString()) as ICrop;
            }
            else if (property.DataType.IsEnum)
            {
                value = Enum.Parse(property.DataType, value.ToString());
            }

            Commands.ChangeProperty cmd = new Commands.ChangeProperty(this.model, property.Name, value);
            this.explorerPresenter.CommandHistory.Add(cmd, true);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Get the value of a variable or model.
        /// </summary>
        /// <param name="namePath">The name of the object to return</param>
        /// <param name="ignoreCase">If true, ignore case when searching for the object or property</param>
        /// <returns>The found object or null if not found</returns>
        private IVariable GetInternal(string namePath, bool ignoreCase = true)
        {
            IModel           relativeTo  = relativeToModel;
            string           cacheKey    = namePath;
            StringComparison compareType = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;

            // Look in cache first.
            object value = null;

            if (cache.ContainsKey(cacheKey))
            {
                value = cache[cacheKey];
            }
            if (value != null)
            {
                return(value as IVariable);
            }

            IVariable returnVariable = null;

            if (namePath == null || namePath.Length == 0)
            {
                return(null);
            }
            else if (namePath[0] != '.' &&
                     namePath.Replace("()", "").IndexOfAny("(+*/".ToCharArray()) != -1)
            {
                // expression - need a better way of detecting an expression
                returnVariable = new VariableExpression(namePath, relativeTo as Model);
            }
            else
            {
                // Remove a square bracketed model name and change our relativeTo model to
                // the referenced model.
                if (namePath.StartsWith("["))
                {
                    int posCloseBracket = namePath.IndexOf(']');
                    if (posCloseBracket == -1)
                    {
                        return(null);
                    }
                    string modelName = namePath.Substring(1, posCloseBracket - 1);
                    namePath = namePath.Remove(0, posCloseBracket + 1);
                    Model foundModel = Apsim.Find(relativeTo, modelName) as Model;
                    if (foundModel == null)
                    {
                        // Didn't find a model with a name matching the square bracketed string so
                        // now try and look for a model with a type matching the square bracketed string.
                        Type[] modelTypes = GetTypeWithoutNameSpace(modelName);
                        if (modelTypes.Length == 1)
                        {
                            foundModel = Apsim.Find(relativeTo, modelTypes[0]) as Model;
                        }
                    }
                    if (foundModel == null)
                    {
                        return(null);
                    }
                    else
                    {
                        relativeTo = foundModel;
                    }
                }
                else if (namePath.StartsWith("."))
                {
                    // Absolute path
                    IModel root = relativeTo;
                    while (root.Parent != null)
                    {
                        root = root.Parent as Model;
                    }
                    relativeTo = root;

                    int posPeriod = namePath.IndexOf('.', 1);
                    if (posPeriod == -1)
                    {
                        posPeriod = namePath.Length;
                    }

                    namePath = namePath.Remove(0, posPeriod);
                    if (namePath.StartsWith("."))
                    {
                        namePath.Remove(1);
                    }
                }

                // Now walk the series of '.' separated path bits, assuming the path bits
                // are child models. Stop when we can't find the child model.
                string[] namePathBits = namePath.Split(".".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                int      i;
                for (i = 0; i < namePathBits.Length; i++)
                {
                    IModel localModel = relativeTo.Children.FirstOrDefault(m => m.Name.Equals(namePathBits[i], compareType));
                    if (localModel == null)
                    {
                        break;
                    }
                    else
                    {
                        relativeTo = localModel as Model;
                    }
                }

                // At this point there are only 2 possibilities. We have encountered a
                // PropertyInfo or the path is invalid.
                // We now need to loop through the remaining path bits and keep track of each
                // section of the path as each section will have to be evaulated everytime a
                // a get is done for this path.
                // The variable 'i' will point to the name path that cannot be found as a model.
                object           relativeToObject = relativeTo;
                List <IVariable> properties       = new List <IVariable>();
                properties.Add(new VariableObject(relativeTo));
                for (int j = i; j < namePathBits.Length; j++)
                {
                    // look for an array specifier e.g. sw[2]
                    string arraySpecifier = null;
                    if (namePathBits[j].Contains("["))
                    {
                        arraySpecifier = StringUtilities.SplitOffBracketedValue(ref namePathBits[j], '[', ']');
                    }

                    // Look for either a property or a child model.
                    IModel localModel = null;
                    if (relativeToObject == null)
                    {
                        return(null);
                    }
                    PropertyInfo propertyInfo = relativeToObject.GetType().GetProperty(namePathBits[j]);
                    if (propertyInfo == null && ignoreCase) // If not found, try using a case-insensitive search
                    {
                        propertyInfo = relativeToObject.GetType().GetProperty(namePathBits[j], BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.IgnoreCase);
                    }
                    if (relativeToObject is IFunction && namePathBits[j] == "Value()")
                    {
                        MethodInfo method = relativeTo.GetType().GetMethod("Value");
                        properties.Add(new VariableMethod(relativeTo, method));
                    }
                    else if (propertyInfo == null && relativeToObject is Model)
                    {
                        // Not a property, may be a child model.
                        localModel = (relativeToObject as IModel).Children.FirstOrDefault(m => m.Name.Equals(namePathBits[i], compareType));
                        if (localModel == null)
                        {
                            return(null);
                        }

                        properties.Add(new VariableObject(localModel));
                        relativeToObject = localModel;
                    }
                    else if (propertyInfo != null)
                    {
                        VariableProperty property = new VariableProperty(relativeToObject, propertyInfo, arraySpecifier);
                        properties.Add(property);
                        relativeToObject = property.Value;
                    }
                    else if (relativeToObject is IList)
                    {
                        // Special case: we are trying to get a property of an array(IList). In this case
                        // we want to return the property value for all items in the array.
                        VariableProperty property = new VariableProperty(relativeToObject, namePathBits[j]);
                        properties.Add(property);
                        relativeToObject = property.Value;
                    }
                    else
                    {
                        return(null);
                    }
                }

                // We now have a list of IVariable instances that can be evaluated to
                // produce a return value for the given path. Wrap the list into an IVariable.
                returnVariable = new VariableComposite(namePath, properties);
            }

            // Add variable to cache.
            cache.Add(cacheKey, returnVariable);

            return(returnVariable);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Get the value of a variable or model.
        /// </summary>
        /// <param name="namePath">The name of the object to return</param>
        /// <param name="relativeTo">The model calling this method</param>
        /// <param name="ignoreCase">If true, ignore case when searching for the object or property</param>
        /// <returns>The found object or null if not found</returns>
        public IVariable GetInternal(string namePath, Model relativeTo, bool ignoreCase = false)
        {
            Model relativeToModel = relativeTo;
            string cacheKey = namePath;
            StringComparison compareType = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;

            // Look in cache first.
            object value = GetFromCache(cacheKey, relativeToModel);
            if (value != null)
            {
                return value as IVariable;
            }

            IVariable returnVariable = null;
            if (namePath == null || namePath.Length == 0)
            {
                return null;
            }
            else if (namePath[0] != '.' && namePath[0] != '.' &&
                     namePath.IndexOfAny("(+*/".ToCharArray()) != -1)
            {
                // expression - need a better way of detecting an expression
                returnVariable = new VariableExpression(namePath, relativeToModel);
            }
            else
            {
                // Remove a square bracketed model name and change our relativeTo model to
                // the referenced model.
                if (namePath.StartsWith("["))
                {
                    int posCloseBracket = namePath.IndexOf(']');
                    if (posCloseBracket == -1)
                    {
                        return null;
                    }
                    string modelName = namePath.Substring(1, posCloseBracket - 1);
                    namePath = namePath.Remove(0, posCloseBracket + 1);
                    Model foundModel = this.Find(modelName, relativeToModel);
                    if (foundModel == null)
                    {
                        // Didn't find a model with a name matching the square bracketed string so
                        // now try and look for a model with a type matching the square bracketed string.
                        Type[] modelTypes = GetTypeWithoutNameSpace(modelName);
                        if (modelTypes.Length == 1)
                            foundModel = this.Find(modelTypes[0], relativeToModel);
                    }
                    if (foundModel == null)
                        return null;
                    else
                        relativeToModel = foundModel;
                }
                else if (namePath.StartsWith("."))
                {
                    // Absolute path
                    Model root = relativeToModel;
                    while (root.Parent != null)
                    {
                        root = root.Parent as Model;
                    }
                    relativeToModel = root;

                    int posPeriod = namePath.IndexOf('.', 1);
                    if (posPeriod == -1)
                    {
                        posPeriod = namePath.Length;
                    }

                    namePath = namePath.Remove(0, posPeriod);
                    if (namePath.StartsWith("."))
                    {
                        namePath.Remove(1);
                    }
                }

                // Now walk the series of '.' separated path bits, assuming the path bits
                // are child models. Stop when we can't find the child model.
                string[] namePathBits = namePath.Split(".".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                int i;
                for (i = 0; i < namePathBits.Length; i++)
                {
                    IModel localModel = relativeToModel.Children.FirstOrDefault(m => m.Name.Equals(namePathBits[i], compareType));
                    if (localModel == null)
                    {
                        break;
                    }
                    else
                    {
                        relativeToModel = localModel as Model;
                    }
                }

                // At this point there are only 2 possibilities. We have encountered a
                // PropertyInfo or the path is invalid.
                // We now need to loop through the remaining path bits and keep track of each
                // section of the path as each section will have to be evaulated everytime a
                // a get is done for this path.
                // The variable 'i' will point to the name path that cannot be found as a model.
                object relativeToObject = relativeToModel;
                List<IVariable> properties = new List<IVariable>();
                properties.Add(new VariableObject(relativeToModel));
                for (int j = i; j < namePathBits.Length; j++)
                {
                    // look for an array specifier e.g. sw[2]
                    string arraySpecifier = null;
                    if (namePathBits[j].Contains("["))
                    {
                        arraySpecifier = StringUtilities.SplitOffBracketedValue(ref namePathBits[j], '[', ']');
                    }

                    // Look for either a property or a child model.
                    IModel localModel = null;
                    if (relativeToObject == null)
                        return null;
                    PropertyInfo propertyInfo = relativeToObject.GetType().GetProperty(namePathBits[j]);
                    if (propertyInfo == null && ignoreCase) // If not found, try using a case-insensitive search
                        propertyInfo = relativeToObject.GetType().GetProperty(namePathBits[j], BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.IgnoreCase);
                    if (propertyInfo == null && relativeToObject is Model)
                    {
                        // Not a property, may be a child model.
                        localModel = (relativeToObject as IModel).Children.FirstOrDefault(m => m.Name.Equals(namePathBits[i], compareType));
                        if (localModel == null)
                        {
                            return null;
                        }

                        properties.Add(new VariableObject(localModel));
                        relativeToObject = localModel;
                    }
                    else if (propertyInfo != null)
                    {
                        VariableProperty property = new VariableProperty(relativeToObject, propertyInfo, arraySpecifier);
                        properties.Add(property);
                        relativeToObject = property.Value;
                    }
                    else if (relativeToObject is IList)
                    {
                        // Special case: we are trying to get a property of an array(IList). In this case
                        // we want to return the property value for all items in the array.
                        VariableProperty property = new VariableProperty(relativeToObject, namePathBits[j]);
                        properties.Add(property);
                        relativeToObject = property.Value;
                    }
                    else
                    {
                        return null;
                    }
                }

                // We now have a list of IVariable instances that can be evaluated to
                // produce a return value for the given path. Wrap the list into an IVariable.
                returnVariable = new VariableComposite(namePath, properties);
            }

            // Add variable to cache.
            AddToCache(cacheKey, relativeTo, returnVariable);

            return returnVariable;
        }
Ejemplo n.º 5
0
        /// <summary>
        /// The view is asking for variable names for its intellisense.
        /// </summary>
        public static List<ContextItem> ExamineTypeForContextItems(Type atype, bool properties, bool methods, bool events)
        {
            List<ContextItem> allItems = new List<ContextItem>();

            // find the properties and methods
            if (atype != null)
            {
                if (properties)
                {
                    foreach (PropertyInfo property in atype.GetProperties(BindingFlags.Instance | BindingFlags.Public))
                    {
                        VariableProperty var = new VariableProperty(atype, property);
                        NeedContextItemsArgs.ContextItem item = new NeedContextItemsArgs.ContextItem();
                        item.Name = var.Name;
                        item.IsProperty = true;
                        item.IsEvent = false;
                        item.IsWriteable = !var.IsReadOnly;
                        item.TypeName = var.DataType.Name;
                        item.Descr = var.Description;
                        item.Units = var.Units;
                        allItems.Add(item);
                    }
                }

                if (methods)
                {
                    foreach (MethodInfo method in atype.GetMethods(BindingFlags.Instance | BindingFlags.Public))
                    {
                        if (!method.Name.StartsWith("get_") && !method.Name.StartsWith("set_"))
                        {
                            DescriptionAttribute descriptionAttribute = ReflectionUtilities.GetAttribute(atype, typeof(DescriptionAttribute), false) as DescriptionAttribute;
                            NeedContextItemsArgs.ContextItem item = new NeedContextItemsArgs.ContextItem();
                            item.Name = method.Name;
                            item.IsProperty = false;
                            item.IsEvent = true;
                            item.IsWriteable = false;
                            item.TypeName = method.ReturnType.Name;
                            if (descriptionAttribute != null)
                                item.Descr = descriptionAttribute.ToString();
                            item.Units = string.Empty;

                            // build a parameter string representation
                            ParameterInfo[] allparams = method.GetParameters();
                            StringBuilder paramText = new StringBuilder("( ");
                            if (allparams.Count() > 0)
                            {
                                for (int p = 0; p < allparams.Count(); p++)
                                {
                                    ParameterInfo parameter = allparams[p];
                                    paramText.Append(parameter.ParameterType.Name + " " + parameter.Name);
                                    if (p < allparams.Count() - 1)
                                        paramText.Append(", ");
                                }
                            }
                            paramText.Append(" )");
                            item.ParamString = paramText.ToString();

                            allItems.Add(item);
                        }
                    }
                }

                if (events)
                {
                    foreach (EventInfo evnt in atype.GetEvents(BindingFlags.Instance | BindingFlags.Public))
                    {
                        NeedContextItemsArgs.ContextItem item = new NeedContextItemsArgs.ContextItem();
                        item.Name = evnt.Name;
                        item.IsProperty = true;
                        item.IsEvent = true;
                        item.IsWriteable = false;
                        item.TypeName = evnt.ReflectedType.Name;
                        item.Descr = "";
                        item.Units = "";
                        allItems.Add(item);
                    }
                }
            }

            allItems.Sort(delegate(ContextItem c1, ContextItem c2) { return c1.Name.CompareTo(c2.Name); });
            return allItems;
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Get the value of a variable or model.
        /// </summary>
        /// <param name="namePath">The name of the object to return</param>
        /// <param name="ignoreCase">If true, ignore case when searching for the object or property</param>
        /// <returns>The found object or null if not found</returns>
        private IVariable GetInternal(string namePath, bool ignoreCase = true)
        {
            IModel           relativeTo  = relativeToModel;
            string           cacheKey    = namePath;
            StringComparison compareType = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;

            // Look in cache first.
            object value = null;

            if (cache.ContainsKey(cacheKey))
            {
                value = cache[cacheKey];
            }
            if (value != null)
            {
                return(value as IVariable);
            }

            IVariable returnVariable = null;

            if (namePath == null || namePath.Length == 0)
            {
                return(null);
            }
            else if (namePath[0] != '.' &&
                     (namePath.Replace("()", "").IndexOfAny("+*/".ToCharArray()) != -1
                      | (namePath.IndexOfAny("(".ToCharArray()) >= 0 && namePath.Substring(0, (namePath.IndexOf('(') >= 0? namePath.IndexOf('(') : 0)).IndexOfAny("[.".ToCharArray()) == -1)))
            {
                // expression - need a better way of detecting an expression
                returnVariable = new VariableExpression(namePath, relativeTo as Model);
            }
            else
            {
                namePath = namePath.Replace("Value()", "Value().");
                // Remove a square bracketed model name and change our relativeTo model to
                // the referenced model.
                if (namePath.StartsWith("["))
                {
                    int posCloseBracket = namePath.IndexOf(']');
                    if (posCloseBracket == -1)
                    {
                        return(null);
                    }
                    string modelName = namePath.Substring(1, posCloseBracket - 1);
                    namePath = namePath.Remove(0, posCloseBracket + 1);
                    Model foundModel = Apsim.Find(relativeTo, modelName) as Model;
                    if (foundModel == null)
                    {
                        // Didn't find a model with a name matching the square bracketed string so
                        // now try and look for a model with a type matching the square bracketed string.
                        Type[] modelTypes = GetTypeWithoutNameSpace(modelName);
                        if (modelTypes.Length == 1)
                        {
                            foundModel = Apsim.Find(relativeTo, modelTypes[0]) as Model;
                        }
                    }
                    if (foundModel == null)
                    {
                        return(null);
                    }
                    else
                    {
                        relativeTo = foundModel;
                    }
                }
                else if (namePath.StartsWith("."))
                {
                    // Absolute path
                    IModel root = relativeTo;
                    while (root.Parent != null)
                    {
                        root = root.Parent as Model;
                    }
                    relativeTo = root;

                    int posPeriod = namePath.IndexOf('.', 1);
                    if (posPeriod == -1)
                    {
                        posPeriod = namePath.Length;
                    }

                    namePath = namePath.Remove(0, posPeriod);
                    if (namePath.StartsWith("."))
                    {
                        namePath.Remove(1);
                    }
                }

                // Now walk the series of '.' separated path bits, assuming the path bits
                // are child models. Stop when we can't find the child model.
                string[] namePathBits = namePath.Split(".".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                int      i;
                for (i = 0; i < namePathBits.Length; i++)
                {
                    IModel localModel = relativeTo.Children.FirstOrDefault(m => m.Name.Equals(namePathBits[i], compareType) && m.Enabled);
                    if (localModel == null)
                    {
                        break;
                    }
                    else
                    {
                        relativeTo = localModel as Model;
                    }
                }

                // At this point there are only 2 possibilities. We have encountered a
                // PropertyInfo/MethodInfo or the path is invalid.
                // We now need to loop through the remaining path bits and keep track of each
                // section of the path as each section will have to be evaulated everytime a
                // a get is done for this path.
                // The variable 'i' will point to the name path that cannot be found as a model.
                object           relativeToObject = relativeTo;
                List <IVariable> properties       = new List <IVariable>();
                properties.Add(new VariableObject(relativeTo));
                for (int j = i; j < namePathBits.Length; j++)
                {
                    // look for an array specifier e.g. sw[2]
                    string arraySpecifier = null;
                    if (namePathBits[j].Contains("["))
                    {
                        arraySpecifier = StringUtilities.SplitOffBracketedValue(ref namePathBits[j], '[', ']');
                    }

                    // Look for either a property or a child model.
                    IModel localModel = null;
                    if (relativeToObject == null)
                    {
                        return(null);
                    }

                    // Check property info
                    PropertyInfo propertyInfo = relativeToObject.GetType().GetProperty(namePathBits[j]);
                    if (propertyInfo == null && ignoreCase) // If not found, try using a case-insensitive search
                    {
                        propertyInfo = relativeToObject.GetType().GetProperty(namePathBits[j], BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.IgnoreCase);
                    }

                    // If not property info
                    // Check method info
                    MethodInfo    methodInfo    = null;
                    List <object> argumentsList = null;
                    if (propertyInfo == null)
                    {
                        if (namePathBits[j].IndexOf('(') > 0)
                        {
                            relativeToObject.GetType().GetMethod(namePathBits[j].Substring(0, namePathBits[j].IndexOf('(')));
                            if (methodInfo == null && ignoreCase) // If not found, try using a case-insensitive search
                            {
                                methodInfo = relativeToObject.GetType().GetMethod(namePathBits[j].Substring(0, namePathBits[j].IndexOf('(')), BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.IgnoreCase);
                            }
                        }
                        if (methodInfo != null)
                        {
                            // get arguments and store in VariableMethod
                            string args = namePathBits[j].Substring(namePathBits[j].IndexOf('('));
                            args = args.Substring(0, args.IndexOf(')'));
                            args = args.Replace("(", "").Replace(")", "");
                            if (args.Length > 0)
                            {
                                argumentsList = new List <object>();
                                args          = args.Trim('(').Trim(')');
                                var argList = args.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                                // get arguments
                                ParameterInfo[] pars = methodInfo.GetParameters();

                                for (int argid = 0; argid < argList.Length; argid++)
                                {
                                    var cleanArg = argList[argid].Trim(' ').Trim(new char[] { '(', ')' }).Trim(' ').Trim('"');
                                    switch (Type.GetTypeCode(pars[argid].ParameterType))
                                    {
                                    case TypeCode.Double:
                                        argumentsList.Add(Convert.ToDouble(cleanArg, CultureInfo.InvariantCulture));
                                        break;

                                    case TypeCode.Int32:
                                        argumentsList.Add(Convert.ToInt32(cleanArg, CultureInfo.InvariantCulture));
                                        break;

                                    case TypeCode.String:
                                        argumentsList.Add(cleanArg);
                                        break;

                                    case TypeCode.Boolean:
                                        argumentsList.Add(Convert.ToBoolean(cleanArg, CultureInfo.InvariantCulture));
                                        break;

                                    default:
                                        throw new ApsimXException(relativeToModel, "The type of argument (" + Type.GetTypeCode(pars[argid].ParameterType) + ") is not currently supported in Report methods");
                                    }
                                }
                            }
                        }
                    }

                    //if (relativeToObject is IFunction && namePathBits[j] == "Value()")
                    //{
                    //    MethodInfo method = relativeTo.GetType().GetMethod("Value");
                    //    properties.Add(new VariableMethod(relativeTo, method));
                    //}
                    //                    else if (propertyInfo == null && methodInfo == null && relativeToObject is Model)

                    if (propertyInfo == null && methodInfo == null && relativeToObject is Model)
                    {
                        // Not a property, may be an unchecked method or a child model.
                        localModel = (relativeToObject as IModel).Children.FirstOrDefault(m => m.Name.Equals(namePathBits[j], compareType));
                        if (localModel == null)
                        {
                            // Not a model
                            return(null);
                        }
                        else
                        {
                            properties.Add(new VariableObject(localModel));
                            relativeToObject = localModel;
                        }
                    }
                    else if (propertyInfo != null)
                    {
                        VariableProperty property = new VariableProperty(relativeToObject, propertyInfo, arraySpecifier);
                        properties.Add(property);
                        relativeToObject = property.Value;
                    }
                    else if (methodInfo != null)
                    {
                        VariableMethod method = null;
                        if (argumentsList != null)
                        {
                            method = new VariableMethod(relativeToObject, methodInfo, argumentsList.ToArray <object>());
                        }
                        else
                        {
                            method = new VariableMethod(relativeToObject, methodInfo, null);
                        }
                        //                        VariableProperty property = new VariableProperty(relativeToObject, propertyInfo, arraySpecifier);
                        properties.Add(method);
                        relativeToObject = method.Value;
                    }
                    else if (relativeToObject is IList)
                    {
                        // Special case: we are trying to get a property of an array(IList). In this case
                        // we want to return the property value for all items in the array.
                        VariableProperty property = new VariableProperty(relativeToObject, namePathBits[j]);
                        properties.Add(property);
                        relativeToObject = property.Value;
                    }
                    else
                    {
                        return(null);
                    }
                }

                // We now have a list of IVariable instances that can be evaluated to
                // produce a return value for the given path. Wrap the list into an IVariable.
                returnVariable = new VariableComposite(namePath, properties);
            }

            // Add variable to cache.
            cache.Add(cacheKey, returnVariable);

            return(returnVariable);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Get the value of a variable or model.
        /// </summary>
        /// <param name="namePath">The name of the object to return</param>
        /// <param name="relativeTo">The model calling this method</param>
        /// <returns>The found object or null if not found</returns>
        public IVariable GetInternal(string namePath, Model relativeTo)
        {
            Model  relativeToModel = relativeTo;
            string cacheKey        = namePath;

            // Look in cache first.
            object value = GetFromCache(cacheKey, relativeToModel);

            if (value != null)
            {
                return(value as IVariable);
            }

            IVariable returnVariable = null;

            if (namePath == null || namePath.Length == 0)
            {
                return(null);
            }
            else if (namePath[0] != '.' && namePath[0] != '.' &&
                     namePath.IndexOfAny("(+*/".ToCharArray()) != -1)
            {
                // expression - need a better way of detecting an expression
                returnVariable = new VariableExpression(namePath, relativeToModel);
            }
            else
            {
                // Remove a square bracketed model name and change our relativeTo model to
                // the referenced model.
                if (namePath.StartsWith("["))
                {
                    int posCloseBracket = namePath.IndexOf(']');
                    if (posCloseBracket == -1)
                    {
                        return(null);
                    }
                    string modelName = namePath.Substring(1, posCloseBracket - 1);
                    namePath = namePath.Remove(0, posCloseBracket + 1);
                    Model foundModel = this.Find(modelName, relativeToModel);
                    if (foundModel == null)
                    {
                        // Didn't find a model with a name matching the square bracketed string so
                        // now try and look for a model with a type matching the square bracketed string.
                        Type[] modelTypes = GetTypeWithoutNameSpace(modelName);
                        if (modelTypes.Length == 1)
                        {
                            foundModel = this.Find(modelTypes[0], relativeToModel);
                        }
                    }
                    if (foundModel == null)
                    {
                        return(null);
                    }
                    else
                    {
                        relativeToModel = foundModel;
                    }
                }
                else if (namePath.StartsWith("."))
                {
                    // Absolute path
                    Model root = relativeToModel;
                    while (root.Parent != null)
                    {
                        root = root.Parent as Model;
                    }
                    relativeToModel = root;

                    int posPeriod = namePath.IndexOf('.', 1);
                    if (posPeriod == -1)
                    {
                        posPeriod = namePath.Length;
                    }

                    namePath = namePath.Remove(0, posPeriod);
                    if (namePath.StartsWith("."))
                    {
                        namePath.Remove(1);
                    }
                }

                // Now walk the series of '.' separated path bits, assuming the path bits
                // are child models. Stop when we can't find the child model.
                string[] namePathBits = namePath.Split(".".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                int      i;
                for (i = 0; i < namePathBits.Length; i++)
                {
                    IModel localModel = relativeToModel.Children.FirstOrDefault(m => m.Name == namePathBits[i]);
                    if (localModel == null)
                    {
                        break;
                    }
                    else
                    {
                        relativeToModel = localModel as Model;
                    }
                }

                // At this point there are only 2 possibilities. We have encountered a
                // PropertyInfo or the path is invalid.
                // We now need to loop through the remaining path bits and keep track of each
                // section of the path as each section will have to be evaulated everytime a
                // a get is done for this path.
                // The variable 'i' will point to the name path that cannot be found as a model.
                object           relativeToObject = relativeToModel;
                List <IVariable> properties       = new List <IVariable>();
                properties.Add(new VariableObject(relativeToModel));
                for (int j = i; j < namePathBits.Length; j++)
                {
                    // look for an array specifier e.g. sw[2]
                    string arraySpecifier = null;
                    if (namePathBits[j].Contains("["))
                    {
                        arraySpecifier = StringUtilities.SplitOffBracketedValue(ref namePathBits[j], '[', ']');
                    }

                    // Look for either a property or a child model.
                    IModel       localModel   = null;
                    PropertyInfo propertyInfo = relativeToObject.GetType().GetProperty(namePathBits[j]);
                    if (propertyInfo == null && relativeToObject is Model)
                    {
                        // Not a property, may be a child model.
                        localModel = (relativeToObject as IModel).Children.FirstOrDefault(m => m.Name == namePathBits[i]);
                        if (localModel == null)
                        {
                            return(null);
                        }

                        properties.Add(new VariableObject(localModel));
                        relativeToObject = localModel;
                    }
                    else if (propertyInfo != null)
                    {
                        VariableProperty property = new VariableProperty(relativeToObject, propertyInfo, arraySpecifier);
                        properties.Add(property);
                        relativeToObject = property.Value;
                    }
                    else
                    {
                        return(null);
                    }
                }

                // We now have a list of IVariable instances that can be evaluated to
                // produce a return value for the given path. Wrap the list into an IVariable.
                returnVariable = new VariableComposite(namePath, properties);
            }

            // Add variable to cache.
            AddToCache(cacheKey, relativeTo, returnVariable);

            return(returnVariable);
        }