Інша річ: ви могли б використати роздуми. Якщо ви кешуєте це належним чином, то він клонуватиме 1000 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 - це лише мій тестовий клас, де я провів десяток тестів, включаючи використання вираження. Ви можете реалізувати це в іншій формі в розширенні чи будь-якому іншому. Не забувайте про кешування.
Я ще не перевіряв серіалізацію, але сумніваюся в поліпшенні з мільйоном класів. Я спробую щось швидке протобуф / ньютон.
PS: для простоти читання я тут використовував лише автоматичну властивість. Я міг би оновити програму FieldInfo, або вам слід легко її реалізувати самостійно.
Нещодавно я перевірив серіалізатор протокольних буферів із функцією DeepClone поза коробкою. Він виграє за 4,2 секунди на мільйоні простих предметів, але коли мова йде про внутрішні об’єкти, він виграє з результатом 7,4 секунди.
Serializer.DeepClone(personList);
РЕЗЮМЕ: Якщо у вас немає доступу до класів, це допоможе. Інакше це залежить від кількості об’єктів. Я думаю, ви могли б використовувати відображення до 10 000 об'єктів (можливо трохи менше), але для цього серіалізатор протокольних буферів працюватиме краще.