Используйте lvalues для создания кода, действительно путающего:
my $foo = undef ;
sub bar:lvalue{ return $foo ;}
# Then later
bar = 5 ;
print bar ;
Если вы управляете объектной моделью, вы можете написать код для этого, но это требует значительного обслуживания. Однако есть много проблем, что означает, что если вам не нужна абсолютно максимальная производительность, то сериализация часто является наиболее управляемым ответом.
Это один из случаев, когда BinaryFormatter
работает приемлемо; обычно я не фанат (из-за проблем с версией и т. д.), но поскольку сериализованные данные предназначены для немедленного использования, это не проблема.
Если вы хотите, чтобы это было немного быстрее (но без вашего собственного кода) , тогда protobuf-net
может помочь, но требует изменения кода (для добавления необходимых метаданных и т. д.). И он основан на дереве (а не на графах).
Другие сериализаторы ( XmlSerializer
, DataContractSerializer
) также подходят, но если это , то просто для клона,
Лучшим способом, вероятно, является реализация интерфейса System.IClonable в вашем объекте и всех его поля, которые также требуют настраиваемых возможностей глубокого клонирования. Затем вы реализуете метод Clone , чтобы вернуть полную копию вашего объекта и его членов.
Пример глубокого клонирования из журнала msdn:
Object DeepClone(Object original)
{
// Construct a temporary memory stream
MemoryStream stream = new MemoryStream();
// Construct a serialization formatter that does all the hard work
BinaryFormatter formatter = new BinaryFormatter();
// This line is explained in the "Streaming Contexts" section
formatter.Context = new StreamingContext(StreamingContextStates.Clone);
// Serialize the object graph into the memory stream
formatter.Serialize(stream, original);
// Seek back to the start of the memory stream before deserializing
stream.Position = 0;
// Deserialize the graph into a new set of objects
// and return the root of the graph (deep copy) to the caller
return (formatter.Deserialize(stream));
}
Вы можете попробовать AltSerialize , который во многих случаях быстрее, чем сериализатор .Net. Он также обеспечивает кэширование и настраиваемые атрибуты для ускорения сериализации.
Если вы запускаете код в среде с частичным доверием, такой как Rackspace Cloud, вам, скорее всего, будет запрещено использовать BinaryFormatter. Вместо этого можно использовать XmlSerializer.
public static T DeepClone<T>(T obj)
{
using (var ms = new MemoryStream())
{
XmlSerializer xs = new XmlSerializer(typeof(T));
xs.Serialize(ms, obj);
ms.Position = 0;
return (T)xs.Deserialize(ms);
}
}