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