/// <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> /// 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> /// Gets enumeration of runtime fields. /// </summary> public static IEnumerable <PhpPropertyInfo> GetRuntimeProperties(this PhpTypeInfo tinfo, object instance) { var runtimefields = tinfo.GetRuntimeFields(instance); if (runtimefields != null && runtimefields.Count != 0) { var enumerator = runtimefields.GetFastEnumerator(); while (enumerator.MoveNext()) { yield return(new PhpPropertyInfo.RuntimeProperty(tinfo, enumerator.CurrentKey)); } } }
/// <summary> /// Gets descriptor representing a runtime field. /// Can be <c>null</c> if type does not support runtime fields. /// </summary> public static PhpPropertyInfo GetRuntimeProperty(this PhpTypeInfo tinfo, string propertyName, object instance) { if (tinfo.RuntimeFieldsHolder != null) { var key = new IntStringKey(propertyName); if (instance != null) { var runtimefields = tinfo.GetRuntimeFields(instance); if (runtimefields == null || runtimefields.Count == 0 || !runtimefields.ContainsKey(key)) { return(null); } } return(new PhpPropertyInfo.RuntimeProperty(tinfo, key)); } else { return(null); } }
/// <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()); } }