Hal lain: Anda bisa menggunakan refleksi. Jika Anda akan menembolok ini dengan benar, maka itu akan mengklon 1.000.000 objek dalam 5,6 detik (sayangnya, 16,4 detik dengan objek dalam).
[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;
}
Saya mengukurnya dengan cara yang sederhana, dengan menggunakan kelas 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;
HASIL: Dengan objek dalam PersonInstance - 16.4, PersonInstance = null - 5.6
CopyFactory hanyalah kelas pengujian saya di mana saya memiliki selusin tes termasuk penggunaan ekspresi. Anda bisa menerapkan ini dalam bentuk lain dalam ekstensi atau apa pun. Jangan lupa tentang caching.
Saya belum menguji serialisasi, tapi saya ragu dengan peningkatan dengan sejuta kelas. Saya akan mencoba sesuatu protobuf cepat / newton.
PS: Demi membaca kesederhanaan, saya hanya menggunakan properti otomatis di sini. Saya dapat memperbarui dengan FieldInfo, atau Anda harus dengan mudah mengimplementasikannya sendiri.
Saya baru-baru ini menguji serializer Protokol Buffer dengan fungsi DeepClone di luar kotak. Ia menang dengan 4,2 detik pada sejuta objek sederhana, tetapi ketika sampai pada objek dalam, ia menang dengan hasil 7,4 detik.
Serializer.DeepClone(personList);
RINGKASAN: Jika Anda tidak memiliki akses ke kelas, maka ini akan membantu. Kalau tidak, itu tergantung pada jumlah objek. Saya pikir Anda bisa menggunakan refleksi hingga 10.000 objek (mungkin sedikit kurang), tetapi untuk lebih dari ini serializer Protokol Buffer akan tampil lebih baik.