示例#1
0
        /// <summary>
        /// Copies fields from <paramref name="source"/> object to <paramref name="target"/> object.
        /// Types of both objects must be the same.
        /// </summary>
        /// <param name="tinfo">Type of both objects.</param>
        /// <param name="source">Source instance.</param>
        /// <param name="target">Target instance.</param>
        public static void MemberwiseClone(PhpTypeInfo tinfo, object source, object target)
        {
            Debug.Assert(tinfo != null);
            Debug.Assert(source != null);
            Debug.Assert(target != null);
            Debug.Assert(source.GetType() == target.GetType());
            Debug.Assert(source.GetType() == tinfo.Type.AsType());

            // copy CLR fields, skipping runtime fields
            foreach (var prop in TypeMembersUtils.EnumerateInstanceFields(source, Utilities.FuncExtensions.Identity <PhpPropertyInfo>(), null, null, ignoreRuntimeFields: true))
            {
                var value = prop.Value.DeepCopy();
                prop.Key.SetValue(null, target, value);
            }

            // fast copy of runtime fields
            var runtime_fields = tinfo.GetRuntimeFields(source);

            if (runtime_fields != null && runtime_fields.Count != 0)
            {
                tinfo.RuntimeFieldsHolder.SetValue(target, runtime_fields.Clone());
            }

            // TODO: traits ?
        }
示例#2
0
 /// <summary>
 /// Returns names and properties of all instance properties or only PHP fields (including runtime fields).
 /// </summary>
 /// <param name="instance">The instance being serialized.</param>
 /// <param name="tinfo"><paramref name="instance"/> type info.</param>
 /// <returns>Name-value pairs. Names are properly formatted for serialization.</returns>
 public static IEnumerable <KeyValuePair <string, PhpValue> > EnumerateSerializableProperties(object /*!*/ instance, PhpTypeInfo tinfo)
 {
     return(TypeMembersUtils.EnumerateInstanceFields(instance,
                                                     FormatSerializedPropertyName,
                                                     TypeMembersUtils.s_keyToString,
                                                     (m) => !m.IsReadOnly));
 }
示例#3
0
 /// <summary>
 /// Returns names and properties of all instance properties or only PHP fields (including runtime fields).
 /// </summary>
 /// <param name="instance">The instance being serialized.</param>
 /// <param name="tinfo"><paramref name="instance"/> type info.</param>
 /// <returns>Name-value pairs. Names are properly formatted for serialization.</returns>
 public static IEnumerable <KeyValuePair <string, PhpValue> > EnumerateSerializableProperties(object /*!*/ instance, PhpTypeInfo tinfo)
 {
     return(TypeMembersUtils.EnumerateInstanceFields(instance,
                                                     (f, d) => Serialization.FormatSerializedPropertyName(f, f.Name, d),
                                                     (k) => k.ToString(),
                                                     (f) => true));
 }
示例#4
0
        /// <summary>
        /// Copies fields from <paramref name="source"/> object to <paramref name="target"/> object.
        /// Types of both objects must be the same.
        /// </summary>
        /// <param name="tinfo">Type of both objects.</param>
        /// <param name="source">Source instance.</param>
        /// <param name="target">Target instance.</param>
        public static void MemberwiseClone(PhpTypeInfo tinfo, object source, object target)
        {
            Debug.Assert(tinfo != null);
            Debug.Assert(source != null);
            Debug.Assert(target != null);
            Debug.Assert(source.GetType() == target.GetType());
            Debug.Assert(source.GetType() == tinfo.Type.AsType());

            // copy CLR fields, skipping runtime fields
            foreach (var prop in TypeMembersUtils.EnumerateInstanceFields(source, (m, d) => m, null, null, true))
            {
                var value = prop.Value.DeepCopy();

                if (prop.Key is FieldInfo f)
                {
                    f.SetValue(target, value.ToClr(f.FieldType));
                }
                else if (prop.Key is PropertyInfo p)
                {
                    p.SetValue(target, value.ToClr(p.PropertyType));
                }
            }

            // fast copy of runtime fields
            var runtime_fields = tinfo.GetRuntimeFields(source);

            if (runtime_fields != null && runtime_fields.Count != 0)
            {
                tinfo.RuntimeFieldsHolder.SetValue(target, runtime_fields.DeepCopy());
            }
        }
示例#5
0
 /// <summary>
 /// Returns names and properties of all instance properties or only PHP fields (including runtime fields).
 /// </summary>
 /// <param name="instance">The instance being serialized.</param>
 /// <param name="tinfo"><paramref name="instance"/> type info.</param>
 /// <returns>Name-value pairs. Names are properly formatted for serialization.</returns>
 public static IEnumerable <KeyValuePair <string, PhpValue> > EnumerateSerializableProperties(object /*!*/ instance, PhpTypeInfo tinfo)
 {
     return(TypeMembersUtils.EnumerateInstanceFields(instance,
                                                     (m, d) => FormatSerializedPropertyName(m is FieldInfo f ? (PhpPropertyInfo) new PhpPropertyInfo.ClrFieldProperty(tinfo, f) : new PhpPropertyInfo.ClrProperty(tinfo, (PropertyInfo)m), d),
                                                     (k) => k.ToString(),
                                                     (m) => (m is PropertyInfo p ? p.SetMethod != null : true) && TypeMembersUtils.s_notClrInternalFieldsPredicate(m)));
 }
 /// <summary>
 /// Returns names and properties of all instance properties or only PHP fields (including runtime fields).
 /// </summary>
 /// <param name="instance">The instance being serialized.</param>
 /// <param name="tinfo"><paramref name="instance"/> type info.</param>
 /// <returns>Name-value pairs. Names are properly formatted for serialization.</returns>
 public static IEnumerable <KeyValuePair <string, PhpValue> > EnumerateSerializableProperties(object /*!*/ instance, PhpTypeInfo tinfo)
 {
     return(TypeMembersUtils.EnumerateInstanceFields(instance,
                                                     (m, d) => FormatSerializedPropertyName(m is FieldInfo f ? (PhpPropertyInfo) new PhpPropertyInfo.ClrFieldProperty(tinfo, f) : new PhpPropertyInfo.ClrProperty(tinfo, (PropertyInfo)m), d),
                                                     (k) => k.ToString(),
                                                     (m) => true));
 }
示例#7
0
        /// <summary>
        /// Creates instance of the class without invoking its constructor.
        /// </summary>
        public object GetUninitializedInstance(Context ctx)
        {
            if (_lazyEmptyCreator == null)
            {
                _lazyEmptyCreator = TypeMembersUtils.BuildCreateEmptyObjectFunc(this);
            }

            return(_lazyEmptyCreator(ctx));
        }
示例#8
0
        /// <summary>
        /// Creates instance of the class without invoking its constructor.
        /// </summary>
        public object GetUninitializedInstance(Context ctx)
        {
            if (_lazyEmptyCreator == null)
            {
                if (TypeMembersUtils.TryBuildCreateEmptyObjectFunc(this, out var activator))
                {
                    _lazyEmptyCreator = activator;
                }
                else
                {
                    _lazyEmptyCreator = (_ctx) =>
                    {
                        Debug.Fail(string.Format(Resources.ErrResources.construct_not_supported, this.Name));
                        return(null);
                    };
                }
            }

            return(_lazyEmptyCreator(ctx));
        }
示例#9
0
        /// <summary>
        /// Copies fields from <paramref name="source"/> object to <paramref name="target"/> object.
        /// Types of both objects must be the same.
        /// </summary>
        /// <param name="tinfo">Type of both objects.</param>
        /// <param name="source">Source instance.</param>
        /// <param name="target">Target instance.</param>
        public static void MemberwiseClone(PhpTypeInfo tinfo, object source, object target)
        {
            Debug.Assert(tinfo != null);
            Debug.Assert(source != null);
            Debug.Assert(target != null);
            Debug.Assert(source.GetType() == target.GetType());
            Debug.Assert(source.GetType() == tinfo.Type.AsType());

            // copy CLR fields, skipping runtime fields
            foreach (var fldvalue in TypeMembersUtils.EnumerateInstanceFields(source, (f, d) => f, null, null, true))
            {
                fldvalue.Key.SetValue(target, fldvalue.Value.DeepCopy());
            }

            // fast copy of runtime fields
            var runtime_fields = tinfo.GetRuntimeFields(source);

            if (runtime_fields != null && runtime_fields.Count != 0)
            {
                tinfo.RuntimeFieldsHolder.SetValue(target, runtime_fields.DeepCopy());
            }
        }
示例#10
0
        /// <summary>
        /// Gets <see cref="Expression"/> representing field value.
        /// </summary>
        /// <param name="name">Class constant name.</param>
        /// <param name="classCtx">Current class context. Can be <c>null</c>.</param>
        /// <param name="target">Expression representing self instance.</param>
        /// <param name="ctx">Expression representing current <see cref="Context"/>.</param>
        /// <param name="kind">Field kind.</param>
        /// <returns><see cref="Expression"/> instance or <c>null</c> if constant does not exist.</returns>
        internal Expression Bind(string name, Type classCtx, Expression target, Expression ctx, FieldKind kind)
        {
            FieldInfo fld;

            //
            if (_fields != null && _fields.TryGetValue(name, out fld) && TypeMembersUtils.IsVisible(fld, classCtx))
            {
                if (fld.IsPublic && fld.IsLiteral)
                {
                    if (kind == FieldKind.Constant)
                    {
                        return(Expression.Constant(fld.GetValue(null)));
                    }
                }

                if (fld.IsStatic)
                {
                    if (kind == FieldKind.InstanceField)
                    {
                        // TODO: Err: static field accessed with instance
                    }
                    return(Expression.Field(null, fld));
                }

                if (kind == FieldKind.InstanceField)
                {
                    Debug.Assert(target != null);
                    return(Expression.Field(target, fld));
                }
            }

            //
            if (kind != FieldKind.InstanceField && _staticsFields != null && _staticsFields.TryGetValue(name, out fld))
            {
                if ((kind == FieldKind.Constant && fld.IsInitOnly) ||
                    (kind == FieldKind.StaticField))
                {
                    Debug.Assert(target == null);
                    Debug.Assert(ctx != null);

                    // Context.GetStatics<_statics>().FIELD
                    var getstatics = BinderHelpers.GetStatic_T_Method(fld.DeclaringType);
                    return(Expression.Field(Expression.Call(ctx, getstatics), fld));
                }
            }

            //
            PropertyInfo p;

            if (kind != FieldKind.Constant && _properties != null && _properties.TryGetValue(name, out p))
            {
                var isstatic = p.GetMethod.IsStatic;
                if ((kind == FieldKind.StaticField) == isstatic)
                {
                    Debug.Assert((target == null) == isstatic);
                    return(Expression.Property(target, p));
                }
            }

            //
            return(null);
        }