/// <summary> /// Creates a new CloneType based on a <see cref="System.Type"/>, gathering all the information that is necessary for cloning. /// </summary> /// <param name="type"></param> public CloneType(Type type) { this.type = type.GetTypeInfo(); this.plainOldData = this.type.IsPlainOldData() || typeof(MemberInfo).GetTypeInfo().IsAssignableFrom(this.type); /* Handle MemberInfo like POD */ this.investigateOwnership = !this.plainOldData; this.surrogate = CloneProvider.GetSurrogateFor(this.type); if (this.type.IsArray) { if (this.type.GetArrayRank() > 1) { throw new NotSupportedException( "Cloning multidimensional arrays is not supported in Duality. " + "Consider skipping the referring field via [CloneField] or [DontSerialize] " + "attribute, or use a regular array instead."); } this.elementType = CloneProvider.GetCloneType(this.type.GetElementType()); } CloneBehaviorAttribute defaultBehaviorAttrib = CloneProvider.GetCloneBehaviorAttribute(this.type); if (defaultBehaviorAttrib != null && defaultBehaviorAttrib.Behavior != CloneBehavior.Default) { this.behavior = defaultBehaviorAttrib.Behavior; } else { this.behavior = CloneBehavior.ChildObject; } }
/// <summary> /// Creates a new CloneType based on a <see cref="System.Type"/>, gathering all the information that is necessary for cloning. /// </summary> /// <param name="type"></param> public CloneType(Type type) { this.type = type; this.plainOldData = this.type.IsPlainOldData() || typeof(MemberInfo).IsAssignableFrom(this.type); /* Handle MemberInfo like POD */ this.investigateOwnership = !this.plainOldData; this.surrogate = CloneProvider.GetSurrogateFor(this.type); if (this.type.IsArray) { this.elementType = CloneProvider.GetCloneType(this.type.GetElementType()); } CloneBehaviorAttribute defaultBehaviorAttrib = CloneProvider.GetCloneBehaviorAttribute(this.type); if (defaultBehaviorAttrib != null && defaultBehaviorAttrib.Behavior != CloneBehavior.Default) { this.behavior = defaultBehaviorAttrib.Behavior; } else { this.behavior = CloneBehavior.ChildObject; } }
public void Init() { if (this.surrogate != null) { return; } if (this.plainOldData) { return; } if (this.type.IsArray) { this.investigateOwnership = !(this.elementType.IsPlainOldData || (this.elementType.Type.IsValueType && !this.elementType.InvestigateOwnership)); return; } else { this.investigateOwnership = typeof(ICloneExplicit).GetTypeInfo().IsAssignableFrom(this.type) || this.surrogate != null; } // Retrieve field data List <CloneField> fieldData = new List <CloneField>(); foreach (FieldInfo field in this.type.DeclaredFieldsDeep()) { if (field.IsStatic) { continue; } if (field.IsInitOnly) { continue; } if (field.HasAttributeCached <ManuallyClonedAttribute>()) { continue; } if (field.DeclaringType.GetTypeInfo().HasAttributeCached <ManuallyClonedAttribute>()) { continue; } CloneFieldFlags flags = CloneFieldFlags.None; CloneFieldAttribute fieldAttrib = field.GetAttributesCached <CloneFieldAttribute>().FirstOrDefault(); if (fieldAttrib != null) { flags = fieldAttrib.Flags; } if (field.HasAttributeCached <DontSerializeAttribute>() && !flags.HasFlag(CloneFieldFlags.DontSkip)) { continue; } if (flags.HasFlag(CloneFieldFlags.Skip)) { continue; } CloneBehaviorAttribute behaviorAttrib = field.GetAttributesCached <CloneBehaviorAttribute>().FirstOrDefault(); CloneType fieldType = CloneProvider.GetCloneType(field.FieldType); bool isAlwaysReference = (behaviorAttrib != null) && (behaviorAttrib.TargetType == null || field.FieldType.GetTypeInfo().IsAssignableFrom(behaviorAttrib.TargetType.GetTypeInfo())) && (behaviorAttrib.Behavior == CloneBehavior.Reference); // Can this field own any objects itself? if (!this.investigateOwnership) { bool fieldCanOwnObjects = true; if (fieldType.IsPlainOldData) { fieldCanOwnObjects = false; } if (isAlwaysReference) { fieldCanOwnObjects = false; } if (fieldType.Type.IsValueType && !fieldType.InvestigateOwnership) { fieldCanOwnObjects = false; } if (fieldCanOwnObjects) { this.investigateOwnership = true; } } CloneField fieldEntry = new CloneField(field, fieldType, flags, behaviorAttrib, isAlwaysReference); fieldData.Add(fieldEntry); } this.fieldData = fieldData.ToArray(); // Build precompile functions for setup and (partially) assignment this.CompileAssignmentFunc(); this.CompileSetupFunc(); this.CompileValueAssignmentFunc(); this.CompileValueSetupFunc(); }