Created
May 18, 2010 19:36
-
-
Save andyedinborough/405432 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Linq; | |
using System.Reflection; | |
namespace ConsoleApplication1 { | |
public class Student { | |
public string Name { get; set; } | |
} | |
public class Students : List<Student> { } | |
/*public class a { | |
public string testa { get; set; } | |
public virtual string Who() { | |
return "I am class a!"; | |
} | |
} | |
public class b : a { | |
public string testb { get; set; } | |
public override string Who() { | |
return "I am class b!"; | |
} | |
}*/ | |
public static class Program { | |
public static Student Student { get; set; } | |
public static Students Students { get; set; } | |
static void Main(string[] args) { | |
// TODO: Initialize properties Student and Students | |
foreach (var student in Students) | |
student.CloneFrom(Student); | |
} | |
/*static void Main(string[] args) { | |
var b = new b() { testa = "a", testb = "b" }; | |
//The version I use in my personal library is faster because it keeps a dictionary | |
//cache of the fields of each type, and creates get/set delegates | |
var a = b.CloneAs<a>(); | |
Debug.Assert(b.Who() == "I am class b!"); | |
Debug.Assert(((a)b).Who() == "I am class b!"); | |
Debug.Assert(a.Who() == "I am class a!"); | |
Debug.Assert(a.testa == "a"); | |
} | |
public static T CloneAs<T>(this T input) where T : new() { | |
var output = new T(); | |
output.CloneFrom(input); | |
return output; | |
}*/ | |
/// <summary> | |
/// Updates one object with the fields of another. | |
/// </summary> | |
public static void CloneFrom<T>(this T ToObj, T FromObj) { | |
CloneFrom(ToObj, FromObj, new Dictionary<object, object>()); | |
} | |
private static FieldInfo[] GetMemberFields(this Type type) { | |
return type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); | |
} | |
private static void CloneFrom<T>(T ToObj, T FromObj, Dictionary<object, object> Values) { | |
Values.Add(FromObj, ToObj); //The dictionary is used to prevent infinite recursion | |
var fields = ToObj.GetType().GetMemberFields(); | |
object value = null; | |
object othervalue = null; | |
foreach (var field in fields) { | |
value = field.GetValue(FromObj); | |
othervalue = field.GetValue(ToObj); | |
if (object.Equals(othervalue, value)) continue; | |
if (value != null && Values.ContainsKey(value)) { | |
//Prevent recursive calls: objA.fieldB.fieldC = objA | |
field.SetValue(ToObj, Values[value]); | |
} else if (othervalue != null && value != null && !field.FieldType.IsPrimitive && !field.FieldType.IsValueType && !(value is string) | |
&& field.FieldType.GetMemberFields().Any()) { | |
//Do not overwrite object references | |
CloneFrom(othervalue, value, Values); | |
} else { | |
field.SetValue(ToObj, value); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment