Autre chose: vous pouvez utiliser la réflexion. Si vous le cachez correctement, il clonera 1 000 000 d'objets en 5,6 secondes (malheureusement, 16,4 secondes avec des objets internes).
[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;
}
Je l'ai mesuré d'une manière simple, en utilisant la classe 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;
RÉSULTAT: avec l'objet interne PersonInstance - 16.4, PersonInstance = null - 5.6
CopyFactory est juste ma classe de test où j'ai une douzaine de tests, y compris l'utilisation de l'expression. Vous pouvez l'implémenter sous une autre forme dans une extension ou autre. N'oubliez pas la mise en cache.
Je n'ai pas encore testé la sérialisation, mais je doute d'une amélioration avec un million de classes. Je vais essayer quelque chose de rapide protobuf / newton.
PS: par souci de simplicité de lecture, je n'ai utilisé ici que la propriété automatique. Je pourrais mettre à jour avec FieldInfo, ou vous devriez facilement l'implémenter par vous-même.
J'ai récemment testé le sérialiseur Protocol Buffers avec la fonction DeepClone prête à l'emploi. Il gagne avec 4,2 secondes sur un million d'objets simples, mais en ce qui concerne les objets intérieurs, il gagne avec le résultat 7,4 secondes.
Serializer.DeepClone(personList);
RÉSUMÉ: Si vous n'avez pas accès aux cours, cela vous aidera. Sinon, cela dépend du nombre d'objets. Je pense que vous pouvez utiliser la réflexion jusqu'à 10 000 objets (peut-être un peu moins), mais pour plus que cela, le sérialiseur Protocol Buffers fonctionnera mieux.