/// <summary>
        /// Creates a StringMemberHelper to get a display string.
        /// </summary>
        /// <param name="property">The property.</param>
        /// <param name="memberName">The member name.</param>
        /// <param name="allowInstanceMember">If <c>true</c>, then StringMemberHelper will look for instance members.</param>
        /// <param name="allowStaticMember">If <c>true</c>, then StringMemberHelper will look for static members.</param>
        /// <exception cref="System.InvalidOperationException">Require either allowInstanceMember or allowStaticMember to be true.</exception>
        public InspectorPropertyValueGetter(InspectorProperty property, string memberName, bool allowInstanceMember = true, bool allowStaticMember = true)
        {
            this.memberProperty = property.FindParent(x => x.Info.GetMemberInfo() != null, true);

            // TODO: Expression temporarily disabled.
            //if (memberName != null && memberName.Length > 0 && memberName[0] == '$')
            //{
            //    var expression = memberName.Substring(1);
            //    this.isStaticExpression = property.ParentValueProperty == null && property.Tree.IsStatic;

            //    this.expressionMethod = ExpressionCompilerUtility.CompileExpression(expression, this.isStaticExpression, property.ParentType, out this.errorMessage);

            //    if (this.expressionMethod != null && this.expressionMethod.Method.ReturnType.IsCastableTo(typeof(TReturnType)) == false)
            //    {
            //        this.errorMessage = "Cannot cast type of " + this.expressionMethod.Method.ReturnType + " to type of " + typeof(TReturnType).Name + ".";
            //        this.expressionMethod = null;
            //    }
            //}
            //else
            {
                var parentType = this.memberProperty.ParentType;

                var finder = MemberFinder.Start(parentType)
                             .HasReturnType <TReturnType>(true)
                             .IsNamed(memberName)
                             .HasNoParameters();

                if (!allowInstanceMember && !allowStaticMember)
                {
                    throw new InvalidOperationException("Require either allowInstanceMember and/or allowStaticMember to be true.");
                }
                else if (!allowInstanceMember)
                {
                    finder.IsStatic();
                }
                else if (!allowStaticMember)
                {
                    finder.IsInstance();
                }

                MemberInfo member;
                if (finder.TryGetMember(out member, out this.errorMessage))
                {
                    if (member is MethodInfo)
                    {
                        memberName += "()";
                    }

                    if (member.IsStatic())
                    {
                        this.staticValueGetter = DeepReflection.CreateValueGetter <TReturnType>(parentType, memberName);
                    }
                    else
                    {
                        this.instanceValueGetter = DeepReflection.CreateWeakInstanceValueGetter <TReturnType>(parentType, memberName);
                    }
                }
            }
        }
        /// <summary>
        /// Creates a StringMemberHelper to get a display string.
        /// </summary>
        /// <param name="property">The property.</param>
        /// <param name="memberName">The member name.</param>
        /// <param name="allowInstanceMember">If <c>true</c>, then StringMemberHelper will look for instance members.</param>
        /// <param name="allowStaticMember">If <c>true</c>, then StringMemberHelper will look for static members.</param>
        /// <exception cref="System.InvalidOperationException">Require either allowInstanceMember or allowStaticMember to be true.</exception>
        public InspectorPropertyValueGetter(InspectorProperty property, string memberName, bool allowInstanceMember = true, bool allowStaticMember = true)
        {
            this.actualProperty = property;
            this.memberProperty = property.FindParent(x => x.Info.GetMemberInfo() != null, true);

            if (memberName != null && memberName.Length > 0 && memberName[0] == '@')
            {
#if ODIN_LIMITED_VERSION
                this.errorMessage = "Expressions are only available in Odin Inspector Commercial and up.";
#else
                var expression = memberName.Substring(1);
                this.isStaticExpression = property.ParentValueProperty == null && property.Tree.IsStatic;

                Type[]   parameters     = new Type[] { typeof(InspectorProperty) };
                string[] parameterNames = new string[] { "property" };

                this.expressionMethod = ExpressionUtility.ParseExpression(expression, this.isStaticExpression, property.ParentType, parameters, parameterNames, out this.errorMessage);

                if (this.expressionMethod != null && this.expressionMethod.Method.ReturnType.IsCastableTo(typeof(TReturnType)) == false)
                {
                    this.errorMessage     = "Cannot cast type of " + this.expressionMethod.Method.ReturnType + " to type of " + typeof(TReturnType).Name + ".";
                    this.expressionMethod = null;
                }
#endif
            }
            else
            {
                if (memberName != null && memberName.Length > 0 && memberName[0] == '$')
                {
                    memberName = memberName.Substring(1);
                }

                var parentType = this.memberProperty.ParentType;

                var finder = MemberFinder.Start(parentType)
                             .HasReturnType <TReturnType>(true)
                             .IsNamed(memberName)
                             .HasNoParameters();

                if (!allowInstanceMember && !allowStaticMember)
                {
                    throw new InvalidOperationException("Require either allowInstanceMember and/or allowStaticMember to be true.");
                }
                else if (!allowInstanceMember)
                {
                    finder.IsStatic();
                }
                else if (!allowStaticMember)
                {
                    finder.IsInstance();
                }

                MemberInfo member;
                if (finder.TryGetMember(out member, out this.errorMessage))
                {
                    if (member is MethodInfo)
                    {
                        memberName += "()";
                    }

                    if (member.IsStatic())
                    {
                        this.staticValueGetter = DeepReflection.CreateValueGetter <TReturnType>(parentType, memberName);
                    }
                    else
                    {
                        this.instanceValueGetter = DeepReflection.CreateWeakInstanceValueGetter <TReturnType>(parentType, memberName);
                    }
                }
            }
        }