อีกอย่าง: คุณสามารถใช้การสะท้อน หากคุณทำการแคชอย่างถูกต้องมันจะทำการโคลนนิ่งวัตถุ 1,000,000 รายการใน 5.6 วินาที (น่าเศร้า 16.4 วินาทีด้วยวัตถุภายใน)
[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class Person
{
...
Job JobDescription
...
}
[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class Job
{...
}
private static readonly Type stringType = typeof (string);
public static class CopyFactory
{
static readonly Dictionary<Type, PropertyInfo[]> ProperyList = new Dictionary<Type, PropertyInfo[]>();
private static readonly MethodInfo CreateCopyReflectionMethod;
static CopyFactory()
{
CreateCopyReflectionMethod = typeof(CopyFactory).GetMethod("CreateCopyReflection", BindingFlags.Static | BindingFlags.Public);
}
public static T CreateCopyReflection<T>(T source) where T : new()
{
var copyInstance = new T();
var sourceType = typeof(T);
PropertyInfo[] propList;
if (ProperyList.ContainsKey(sourceType))
propList = ProperyList[sourceType];
else
{
propList = sourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
ProperyList.Add(sourceType, propList);
}
foreach (var prop in propList)
{
var value = prop.GetValue(source, null);
prop.SetValue(copyInstance,
value != null && prop.PropertyType.IsClass && prop.PropertyType != stringType ? CreateCopyReflectionMethod.MakeGenericMethod(prop.PropertyType).Invoke(null, new object[] { value }) : value, null);
}
return copyInstance;
}
ฉันวัดด้วยวิธีง่ายๆโดยใช้คลาส Watcher
var person = new Person
{
...
};
for (var i = 0; i < 1000000; i++)
{
personList.Add(person);
}
var watcher = new Stopwatch();
watcher.Start();
var copylist = personList.Select(CopyFactory.CreateCopyReflection).ToList();
watcher.Stop();
var elapsed = watcher.Elapsed;
ผลลัพธ์:ด้วยวัตถุภายใน PersonInstance - 16.4, PersonInstance = null - 5.6
CopyFactory เป็นเพียงคลาสทดสอบของฉันที่ฉันมีการทดสอบหลายสิบครั้งรวมถึงการใช้นิพจน์ คุณสามารถใช้สิ่งนี้ในรูปแบบอื่นในส่วนขยายหรืออะไรก็ได้ อย่าลืมเกี่ยวกับแคช
ฉันยังไม่ได้ทดสอบการทำให้เป็นอันดับ แต่ฉันสงสัยในการปรับปรุงด้วยการเรียนเป็นล้านครั้ง ฉันจะลอง protobuf / newton ที่รวดเร็ว
PS: เพื่อความง่ายในการอ่านฉันใช้ Auto-Property ที่นี่เท่านั้น ฉันสามารถอัปเดตด้วย FieldInfo หรือคุณควรใช้สิ่งนี้ด้วยตัวเอง
ฉันเพิ่งทดสอบProtocolizer บัฟเฟอร์ serializer กับฟังก์ชั่น DeepClone ออกจากกล่อง มันชนะด้วย 4.2 วินาทีในวัตถุเรียบง่ายนับล้านชิ้น แต่เมื่อมันมาถึงวัตถุภายในมันจะชนะด้วยผลลัพธ์ 7.4 วินาที
Serializer.DeepClone(personList);
สรุป:หากคุณไม่มีสิทธิ์เข้าถึงชั้นเรียนสิ่งนี้จะช่วยได้ มิฉะนั้นจะขึ้นอยู่กับจำนวนวัตถุ ฉันคิดว่าคุณสามารถใช้การสะท้อนวัตถุได้มากถึง 10,000 วัตถุ (อาจจะน้อยกว่านี้) แต่สำหรับมากกว่านี้ตัวจัดการโพรโทคอลบัฟเฟอร์จะทำงานได้ดีขึ้น