示例#1
0
        /// <summary>
        /// Imports the delegate to the specified member.
        /// </summary>
        /// <param name="scriptObject">The script object to import into</param>
        /// <param name="member">The member.</param>
        /// <param name="function">The function delegate.</param>
        /// <exception cref="ArgumentNullException">if member or function are null</exception>
        public static void Import(this IScriptObject scriptObject, string member, Delegate function)
        {
            if (member == null)
            {
                throw new ArgumentNullException(nameof(member));
            }
            if (function == null)
            {
                throw new ArgumentNullException(nameof(function));
            }

            scriptObject.SetValue(null, new SourceSpan(), member, DynamicCustomFunction.Create(function.Target, function.GetMethodInfo()), true);
        }
示例#2
0
        /// <summary>
        /// Imports the specified object.
        /// </summary>
        /// <param name="scriptObject">The script object to import into</param>
        /// <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="ArgumentOutOfRangeException">The object is not importable.</exception>
        public static void Import(this IScriptObject scriptObject, object obj, ScriptMemberImportFlags flags, MemberFilterDelegate filter = null, MemberRenamerDelegate renamer = null)
        {
            if (obj == null)
            {
                return;
            }

            if (!ScriptObject.IsImportable(obj))
            {
                throw new ArgumentOutOfRangeException(nameof(obj), string.Format(RS.InvalidObjectType, obj.GetType()));
            }

#if NETSTANDARD
            TypeInfo typeInfo = (obj as Type ?? obj.GetType()).GetTypeInfo();
#else
            Type typeInfo = (obj as Type ?? obj.GetType()).GetTypeInfo();
#endif

            bool useStatic   = false;
            bool useInstance = false;
            if (obj is Type)
            {
                useStatic = true;
                obj       = null;
            }
            else
            {
                useInstance = true;
            }

            renamer = renamer ?? StandardMemberRenamer.Default;

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

                        bool keep = field.GetCustomAttribute <ScriptMemberIgnoreAttribute>() == null;
                        if (keep && ((field.IsStatic && useStatic) || useInstance))
                        {
                            string newFieldName = renamer(field);
                            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
                            scriptObject.SetValue(null, new SourceSpan(), newFieldName, field.GetValue(obj), field.IsInitOnly || field.IsLiteral);
                        }
                    }
                }

                if ((flags & ScriptMemberImportFlags.Property) != 0)
                {
                    foreach (PropertyInfo property in typeInfo.GetDeclaredProperties())
                    {
                        // Workaround with .NET Core, extension method is not working (retuning null)
#if NETFX
                        MethodInfo getMethod = property.GetGetMethod();
#else
                        MethodInfo getMethod = property.GetMethod;
#endif

                        if (!property.CanRead || !getMethod.IsPublic)
                        {
                            continue;
                        }

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

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

                            // Initially, we were setting readonly depending on the precense of a set method, but this is not compatible with liquid implems, so we remove readonly restriction
                            //script.SetValue(null, new SourceSpan(), newPropertyName, property.GetValue(obj), property.GetSetMethod() == null || !property.GetSetMethod().IsPublic);
                            scriptObject.SetValue(null, new SourceSpan(), newPropertyName, property.GetValue(obj), false);
                        }
                    }
                }

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

                        bool keep = method.GetCustomAttribute <ScriptMemberIgnoreAttribute>() == null;
                        if (keep && method.IsPublic && method.IsStatic && !method.IsSpecialName)
                        {
                            string newMethodName = renamer(method);
                            if (string.IsNullOrEmpty(newMethodName))
                            {
                                newMethodName = method.Name;
                            }

                            scriptObject.SetValue(null, new SourceSpan(), newMethodName, DynamicCustomFunction.Create(obj, method), true);
                        }
                    }
                }

                if (typeInfo.BaseType == typeof(object))
                {
                    break;
                }

                typeInfo = typeInfo.BaseType.GetTypeInfo();
            }
        }