/// <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); }
/// <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(); } }