/// <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.copyByAssignment = this.type.IsDeepCopyByAssignment() || typeof(MemberInfo).GetTypeInfo().IsAssignableFrom(this.type); /* Handle MemberInfo like POD */ this.investigateOwnership = !this.copyByAssignment; 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 Cohee. " + "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; } }
private void PrepareCloneGraph() { // Visit the object graph in order to determine which objects to clone this.PrepareObjectCloneGraph(this.sourceRoot, this.targetRoot, null, CloneBehavior.ChildObject); this.localBehavior.Clear(); // Determine which weak references to keep if (this.dropWeakReferences.Count > 0) { foreach (object source in this.targetMapping.Keys) { this.dropWeakReferences.Remove(source); if (this.dropWeakReferences.Count == 0) { break; } } } // Perform late setup for surrogate objects that required it foreach (LateSetupEntry lateSetup in this.lateSetupSchedule) { CloneType typeData = GetCloneType((lateSetup.Source ?? lateSetup.Target).GetType()); ICloneSurrogate surrogate = typeData.Surrogate; object lateSetupTarget = lateSetup.Target; surrogate.LateSetup(lateSetup.Source, ref lateSetupTarget, this); this.SetTargetOf(lateSetup.Source ?? lateSetup.Target, lateSetupTarget); } }
/// <summary> /// Copies the base objects data to the specified target object. /// </summary> /// <param name="baseObj"></param> /// <param name="targetObj"></param> /// <param name="fields"></param> public void CopyObjectTo <T>(T baseObj, T targetObj, IEnumerable <FieldInfo> fields = null) { if (fields == null) { Type objType = baseObj.GetType(); if (!this.DoesUnwrapType(objType)) { return; } // IClonables if (baseObj is ICloneExplicit) { (baseObj as ICloneExplicit).CopyDataTo(targetObj, this); return; } // ISurrogate ICloneSurrogate surrogate = GetSurrogateFor(objType); if (surrogate != null) { surrogate.RealObject = baseObj; surrogate.CopyDataTo(targetObj, this); return; } fields = objType.GetAllFields(ReflectionHelper.BindInstanceAll); } foreach (FieldInfo f in fields) { f.SetValue(targetObj, this.RequestObjectClone(f.GetValue(baseObj))); } }
/// <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; }
private void PrepareCloneGraph() { // Visit the object graph in order to determine which objects to clone this.PrepareObjectCloneGraph(this.sourceRoot, this.targetRoot, null, CloneBehavior.ChildObject); this.localBehavior.Clear(); // Perform late setup for surrogate objects that required it foreach (LateSetupEntry lateSetup in this.lateSetupSchedule) { CloneType typeData = GetCloneType((lateSetup.Source ?? lateSetup.Target).GetType()); ICloneSurrogate surrogate = typeData.Surrogate; object lateSetupTarget = lateSetup.Target; surrogate.LateSetup(lateSetup.Source, ref lateSetupTarget, this); this.SetTargetOf(lateSetup.Source ?? lateSetup.Target, lateSetupTarget); } }
/// <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; } }
protected virtual object CloneObject(object baseObj) { Type objType = baseObj.GetType(); if (!this.DoesUnwrapType(objType)) { return(baseObj); } // IClonables if (baseObj is ICloneExplicit) { object copy = objType.CreateInstanceOf() ?? objType.CreateInstanceOf(true); if (objType.IsClass) { this.RegisterObjectClone(baseObj, copy); } (baseObj as ICloneExplicit).CopyDataTo(copy, this); return(copy); } // ISurrogate ICloneSurrogate surrogate = GetSurrogateFor(objType); if (surrogate != null) { surrogate.RealObject = baseObj; object copy = surrogate.CreateTargetObject(this); if (objType.IsClass) { this.RegisterObjectClone(baseObj, copy); } surrogate.CopyDataTo(copy, this); return(copy); } // Shallow types, cloned by assignment if (objType.IsDeepByValueType()) { return(baseObj); } // Arrays else if (objType.IsArray) { Array baseArray = (Array)baseObj; Type elemType = objType.GetElementType(); int length = baseArray.Length; Array copy = Array.CreateInstance(elemType, length); this.RegisterObjectClone(baseObj, copy); bool unwrap = this.DoesUnwrapType(elemType); if (unwrap) { for (int i = 0; i < length; ++i) { copy.SetValue(this.RequestObjectClone(baseArray.GetValue(i)), i); } } else if (!elemType.IsValueType) { for (int i = 0; i < length; ++i) { object obj = baseArray.GetValue(i); copy.SetValue(this.GetRegisteredObjectClone(obj) ?? obj, i); } } else { baseArray.CopyTo(copy, 0); } return(copy); } // Reference types / complex objects else { object copy = objType.CreateInstanceOf() ?? objType.CreateInstanceOf(true); if (objType.IsClass) { this.RegisterObjectClone(baseObj, copy); } this.CopyObjectTo(baseObj, copy, objType.GetAllFields(ReflectionHelper.BindInstanceAll)); return(copy); } }