예제 #1
0
            /// <summary>
            /// Sets property value dynamically on the newly instantiated object.
            /// </summary>
            protected static void SetProperty(object /*!*/ instance, PhpTypeInfo tinfo, string /*!*/ name, PhpValue value, Context /*!*/ context)
            {
                // the property name might encode its visibility and "classification" -> use these
                // information for suitable property desc lookups
                FieldAttributes visibility;
                string          type_name;
                string          property_name = Serialization.ParseSerializedPropertyName(name, out type_name, out visibility);

                var declarer = (type_name == null)
                    ? tinfo
                    : context.GetDeclaredType(type_name, true) ?? tinfo;

                // try to find a suitable field handle
                var fld = TypeMembersUtils.ResolveInstanceField(tinfo, property_name);

                if (fld != null && TypeMembersUtils.IsVisible(fld, declarer.Type.AsType()))
                {
                    if ((fld.IsPrivate && declarer.Type.AsType() != fld.DeclaringType))
                    {
                        // if certain conditions are met, don't use the handle even if it was found
                        // (this is to precisely mimic the PHP behavior)
                        fld = null;
                    }
                }

                if (fld != null)
                {
                    fld.SetValue(instance, value);
                }
                else if (tinfo.RuntimeFieldsHolder != null)
                {
                    // suitable CT field not found -> add it to RT fields
                    // (note: care must be taken so that the serialize(unserialize($x)) round
                    // trip returns $x even if user classes specified in $x are not declared)
                    var runtime_fields = tinfo.GetRuntimeFields(instance);
                    if (runtime_fields == null)
                    {
                        runtime_fields = new PhpArray(1);
                        tinfo.RuntimeFieldsHolder.SetValue(instance, runtime_fields);
                    }
                    runtime_fields[name] = value;
                }
                else
                {
                    throw new ArgumentException();
                }
            }
예제 #2
0
                IEnumerable <KeyValuePair <string, PhpValue> > EnumerateSerializableProperties(object obj, PhpTypeInfo tinfo, PhpArray properties)
                {
                    Debug.Assert(obj != null);
                    Debug.Assert(tinfo != null);
                    Debug.Assert(properties != null);

                    PhpArray runtime_fields = null;

                    var enumerator = properties.GetFastEnumerator();

                    while (enumerator.MoveNext())
                    {
                        // TODO: PhpFieldInfo instead of System.Reflection.FieldInfo

                        FieldAttributes visibility;
                        string          name = enumerator.CurrentValue.ToStringOrThrow(_ctx);
                        string          declaring_type_name;
                        string          property_name = Serialization.ParseSerializedPropertyName(name, out declaring_type_name, out visibility);

                        PhpTypeInfo declarer;   // for visibility check
                        if (declaring_type_name == null)
                        {
                            declarer = tinfo;
                        }
                        else
                        {
                            declarer = _ctx.GetDeclaredType(declaring_type_name);
                            if (declarer == null)
                            {
                                // property name refers to an unknown class -> value will be null
                                yield return(new KeyValuePair <string, PhpValue>(name, PhpValue.Null));

                                continue;
                            }
                        }

                        // obtain the property desc and decorate the prop name according to its visibility and declaring class
                        var fld = TypeMembersUtils.ResolveInstanceField(tinfo, name);
                        if (fld != null && TypeMembersUtils.IsVisible(fld, declarer.Type.AsType()))
                        {
                            var fld_declarer = fld.DeclaringType;

                            // if certain conditions are met, serialize the property as null
                            // (this is to precisely mimic the PHP behavior)
                            if ((visibility == (fld.Attributes & FieldAttributes.FieldAccessMask) && visibility != FieldAttributes.Public) ||
                                (visibility == FieldAttributes.Private && declarer.Type.AsType() != fld_declarer))
                            {
                                yield return(new KeyValuePair <string, PhpValue>(name, PhpValue.Null));

                                continue;
                            }

                            name = Serialization.FormatSerializedPropertyName(fld, property_name, fld_declarer.GetPhpTypeInfo());
                        }
                        else
                        {
                            fld = null; // field is not visible, try runtime fields
                        }

                        // obtain the property value
                        PhpValue val;

                        if (fld != null)
                        {
                            val = PhpValue.FromClr(fld.GetValue(obj));
                        }
                        else
                        {
                            if (runtime_fields == null)
                            {
                                runtime_fields = tinfo.GetRuntimeFields(obj) ?? PhpArray.Empty;
                            }

                            if (!runtime_fields.TryGetValue(name, out val))
                            {
                                // PHP 5.1+
                                PhpException.Throw(PhpError.Notice, string.Format(Core.Resources.ErrResources.sleep_returned_bad_field, name));
                            }
                        }

                        yield return(new KeyValuePair <string, PhpValue>(name, val));
                    }
                }