Exemple #1
0
        /// <summary>
        /// Get the value of a property on this object at the specified path
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="path">The path, consisting of property names and sub-property names
        /// separated by '.' characters.  For example: 'PropertyName.SubPropertyName.SubSubPropertyName' etc.
        /// Parameterless methods may also be invoked by adding '()', i.e.:
        /// 'PropertyName.SubMethodName().SubSubPropertyName'.
        /// Methods and properties on the optional context object may also be invoked in the same way, via a
        /// '*' redirection.  For example: '*.MethodName()'.  When switching to the context
        /// object the SetSourceObject method on it will be called and the current object or property value
        /// passed in.  This allows for complex operations to be performed in order to return a value
        /// provided that functionality is implemented in a suitable context object provided.</param>
        /// <param name="context">The (optional) string conversion context object.  If supplies this allows
        /// the '*' symbol to be used within property paths in order to access properties and
        /// functions supplied on the context object.</param>
        /// <returns></returns>
        public static object GetFromPath(this object obj, string path, IStringConversionContext context = null)
        {
            foreach (string substring in path.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries))
            {
                string token = substring;
                if (obj == null)
                {
                    return(null);
                }

                Type type = obj.GetType();

                if (token.EqualsIgnoreCase(TextFormat.CONTEXT))
                {
                    context.SetSourceObject(obj);
                    obj = context;
                }
                else if (token.EndsWith("()")) // Method
                {
                    MethodInfo info = type.GetMethod(token.TrimEnd(')', '('), new Type[] { });
                    if (info == null)
                    {
                        return(null);
                    }
                    else
                    {
                        obj = info.Invoke(obj, null);
                    }
                }
                else // Property...
                {
                    PropertyInfo info;
                    string       key = null;
                    if (token.EndsWith("]"))
                    {
                        token = token.TrimEnd(']');
                        int keyStart = token.LastIndexOf('[');
                        if (keyStart >= 0)
                        {
                            key   = token.Substring(keyStart + 1);
                            token = token.Substring(0, keyStart);
                            if (keyStart == 0)
                            {
                                token = "Item";
                            }
                        }
                    }
                    if (key != null)
                    {
                        info = type.GetProperty(token, new Type[] { key.GetType() });
                        if (info == null)
                        {
                            //Property accessor isn't indexed, but maybe the object itself is...
                            info = type.GetProperty(token);
                            if (info != null)
                            {
                                obj = info.GetValue(obj, null);
                                if (obj != null)
                                {
                                    info = obj.GetType().GetProperty("Item", new Type[] { key.GetType() });
                                }
                            }
                        }
                    }
                    else
                    {
                        info = type.GetProperty(token);
                    }
                    if (info == null)
                    {
                        //...or Field?
                        FieldInfo fInfo = type.GetField(token);
                        if (fInfo == null)
                        {
                            return(null);
                        }
                        else
                        {
                            obj = fInfo.GetValue(obj);
                        }
                    }
                    else
                    {
                        if (key != null)
                        {
                            obj = info.GetValue(obj, new object[] { key });
                        }
                        else
                        {
                            obj = info.GetValue(obj, null);
                        }
                    }
                }
            }
            return(obj);
        }