/// <summary>
        /// Imports the specified object intto this <see cref="ScriptObject"/> context. See remarks.
        /// </summary>
        /// <param name="obj">The object.</param>
        /// <param name="filter">Optional member filterer</param>
        /// <param name="renamer">Optional renamer</param>
        /// <remarks>
        /// <ul>
        /// <li>If <paramref name="obj"/> is a <see cref="System.Type"/>, this method will import only the static field/properties of the specified object.</li>
        /// <li>If <paramref name="obj"/> is a <see cref="ScriptObject"/>, this method will import the members of the specified object into the new object.</li>
        /// <li>If <paramref name="obj"/> is a plain object, this method will import the public fields/properties of the specified object into the <see cref="ScriptObject"/>.</li>
        /// </ul>
        /// </remarks>
        public static void Import(this IScriptObject script, object obj, FilterMemberDelegate filter = null, MemberRenamerDelegate renamer = null)
        {
            if (obj is IScriptObject)
            {
                script.Import((IScriptObject)obj);
                return;
            }

            script.Import(obj, ScriptMemberImportFlags.All, filter, renamer);
        }
Example #2
0
        /// <summary>
        /// Imports the specified object.
        /// </summary>
        /// <param name="obj">The object.</param>
        /// <param name="flags">The import flags.</param>
        /// <param name="filter">A filter applied on each member</param>
        /// <param name="renamer">The member renamer.</param>
        /// <exception cref="System.ArgumentOutOfRangeException"></exception>
        public static void Import(this IScriptObject script, object obj, ScriptMemberImportFlags flags, FilterMemberDelegate filter = null, MemberRenamerDelegate renamer = null)
        {
            if (obj == null)
            {
                return;
            }
            if (!ScriptObject.IsImportable(obj))
            {
                throw new ArgumentOutOfRangeException(nameof(obj), $"Unsupported object type [{obj.GetType()}]. Expecting plain class or struct");
            }

            var  typeInfo          = (obj as Type ?? obj.GetType()).GetTypeInfo();
            bool useStatic         = false;
            bool useInstance       = false;
            bool useMethodInstance = false;

            if (obj is Type)
            {
                useStatic = true;
                obj       = null;
            }
            else
            {
                useInstance       = true;
                useMethodInstance = (flags & ScriptMemberImportFlags.MethodInstance) != 0;
            }

            renamer = renamer ?? StandardMemberRenamer.Default;

            if ((flags & ScriptMemberImportFlags.Field) != 0)
            {
                foreach (var field in typeInfo.GetDeclaredFields())
                {
                    if (!field.IsPublic)
                    {
                        continue;
                    }
                    if (filter != null && !filter(field.Name))
                    {
                        continue;
                    }

                    var keep = field.GetCustomAttribute <ScriptMemberIgnoreAttribute>() == null;
                    if (keep && ((field.IsStatic && useStatic) || useInstance))
                    {
                        var newFieldName = renamer(field.Name);
                        if (String.IsNullOrEmpty(newFieldName))
                        {
                            newFieldName = field.Name;
                        }

                        // If field is init only or literal, it cannot be set back so we mark it as read-only
                        script.SetValue(null, new SourceSpan(), newFieldName, field.GetValue(obj), field.IsInitOnly || field.IsLiteral);
                    }
                }
            }

            if ((flags & ScriptMemberImportFlags.Property) != 0)
            {
                foreach (var property in typeInfo.GetDeclaredProperties())
                {
                    if (!property.CanRead || !property.GetGetMethod().IsPublic)
                    {
                        continue;
                    }

                    if (filter != null && !filter(property.Name))
                    {
                        continue;
                    }

                    var keep = property.GetCustomAttribute <ScriptMemberIgnoreAttribute>() == null;
                    if (keep && (((property.GetGetMethod().IsStatic&& useStatic) || useInstance)))
                    {
                        var newPropertyName = renamer(property.Name);
                        if (String.IsNullOrEmpty(newPropertyName))
                        {
                            newPropertyName = property.Name;
                        }

                        script.SetValue(null, new SourceSpan(), newPropertyName, property.GetValue(obj), property.GetSetMethod() == null || !property.GetSetMethod().IsPublic);
                    }
                }
            }

            if ((flags & ScriptMemberImportFlags.Method) != 0 && (useStatic || useMethodInstance))
            {
                foreach (var method in typeInfo.GetDeclaredMethods())
                {
                    if (filter != null && !filter(method.Name))
                    {
                        continue;
                    }

                    var keep = method.GetCustomAttribute <ScriptMemberIgnoreAttribute>() == null;
                    if (keep && method.IsPublic && ((useMethodInstance && !method.IsStatic) || (useStatic && method.IsStatic)) && !method.IsSpecialName)
                    {
                        var newMethodName = renamer(method.Name);
                        if (String.IsNullOrEmpty(newMethodName))
                        {
                            newMethodName = method.Name;
                        }

                        script.SetValue(null, new SourceSpan(), newMethodName, new ObjectFunctionWrapper(obj, method), true);
                    }
                }
            }
        }
        /// <summary>
        /// Imports the specified object.
        /// </summary>
        /// <param name="obj">The object.</param>
        /// <param name="flags">The import flags.</param>
        /// <param name="filter">A filter applied on each member</param>
        /// <param name="renamer">The member renamer.</param>
        /// <exception cref="System.ArgumentOutOfRangeException"></exception>
        public static void Import(this IScriptObject script, object obj, ScriptMemberImportFlags flags, FilterMemberDelegate filter = null, IMemberRenamer renamer = null)
        {
            if (obj == null)
            {
                return;
            }
            if (!ScriptObject.IsImportable(obj))
            {
                throw new ArgumentOutOfRangeException(nameof(obj), $"Unsupported object type [{obj.GetType()}]. Expecting plain class or struct");
            }

            var typeInfo = (obj as Type ?? obj.GetType()).GetTypeInfo();
            bool useStatic = false;
            bool useInstance = false;
            bool useMethodInstance = false;
            if (obj is Type)
            {
                useStatic = true;
                obj = null;
            }
            else
            {
                useInstance = true;
                useMethodInstance = (flags & ScriptMemberImportFlags.MethodInstance) != 0;
            }

            renamer = renamer ?? StandardMemberRenamer.Default;

            if ((flags & ScriptMemberImportFlags.Field) != 0)
            {
                foreach (var field in typeInfo.GetDeclaredFields())
                {
                    if (!field.IsPublic)
                    {
                        continue;
                    }
                    if (filter != null && !filter(field.Name))
                    {
                        continue;
                    }

                    var keep = field.GetCustomAttribute<ScriptMemberIgnoreAttribute>() == null;
                    if (keep && ((field.IsStatic && useStatic) || useInstance))
                    {
                        var newFieldName = renamer.GetName(field.Name);
                        if (String.IsNullOrEmpty(newFieldName))
                        {
                            newFieldName = field.Name;
                        }

                        // If field is init only or literal, it cannot be set back so we mark it as read-only
                        script.SetValue(newFieldName, field.GetValue(obj), field.IsInitOnly || field.IsLiteral);
                    }
                }
            }

            if ((flags & ScriptMemberImportFlags.Property) != 0)
            {
                foreach (var property in typeInfo.GetDeclaredProperties())
                {
                    if (!property.CanRead || !property.GetGetMethod().IsPublic)
                    {
                        continue;
                    }

                    if (filter != null && !filter(property.Name))
                    {
                        continue;
                    }

                    var keep = property.GetCustomAttribute<ScriptMemberIgnoreAttribute>() == null;
                    if (keep && (((property.GetGetMethod().IsStatic && useStatic) || useInstance)))
                    {
                        var newPropertyName = renamer.GetName(property.Name);
                        if (String.IsNullOrEmpty(newPropertyName))
                        {
                            newPropertyName = property.Name;
                        }

                        script.SetValue(newPropertyName, property.GetValue(obj), property.GetSetMethod() == null || !property.GetSetMethod().IsPublic);
                    }
                }
            }

            if ((flags & ScriptMemberImportFlags.Method) != 0 && (useStatic || useMethodInstance))
            {
                foreach (var method in typeInfo.GetDeclaredMethods())
                {
                    if (filter != null && !filter(method.Name))
                    {
                        continue;
                    }

                    var keep = method.GetCustomAttribute<ScriptMemberIgnoreAttribute>() == null;
                    if (keep && method.IsPublic && ((useMethodInstance && !method.IsStatic) || (useStatic && method.IsStatic)) && !method.IsSpecialName)
                    {
                        var newMethodName = renamer.GetName(method.Name);
                        if (String.IsNullOrEmpty(newMethodName))
                        {
                            newMethodName = method.Name;
                        }

                        script.SetValue(newMethodName, new ObjectFunctionWrapper(obj, method), true);
                    }
                }
            }
        }