Faster deep cloning

前端 未结 9 717
深忆病人
深忆病人 2020-12-02 13:44

Does anyone want a framework/class which allows me to clone by values .Net objects? I\'m only interested with public read/write properties (namely DataContracts), and I don\

相关标签:
9条回答
  • 2020-12-02 14:08

    I don't know whether this suits your requirements exactly, but you could also create a deep clone using a BinaryFormatter. See this answer to a related question (by Binoj Antony):

    public static class GenericCopier<T>
    {
        public static T DeepCopy(object objectToCopy)
        {
            using (MemoryStream memoryStream = new MemoryStream())
            {
                BinaryFormatter binaryFormatter = new BinaryFormatter();
                binaryFormatter.Serialize(memoryStream, objectToCopy);
                memoryStream.Seek(0, SeekOrigin.Begin);
                return (T) binaryFormatter.Deserialize(memoryStream);
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-02 14:09

    There is probably no full working cloning code made by IL Emit on the internet.

    But IL Emit is of the same speed as code by Expression Trees, because both methods end up with similar compiled lambda copy functions. Expression Trees are approximately 4x faster than Reflection. The best thing is that Expression Trees general cloning function is available on the internet.

    One implemetation by expression trees was already mentioned by Cygon. New thoroughly tested implementation can be found in the CodeProject article Fast Deep Copy by Expression Trees (C#).

    Use the extension method by

    var copy = originalObject.DeepCopyByExpressionTree();
    
    0 讨论(0)
  • 2020-12-02 14:12

    If you are talking about an object tree/graph:

    Writing specific IL to serialize an object is tricky. IMO, your best bet is to look at a full serialization, like how DataContractSerializer would work - but not necessarily with that engine.

    For example, protobuf-net has a Serializer.DeepClone<T> method that might help. It should be faster than DataContractSerializer, at least. At the current time, you need to add some clues for the serializer (even if just [ProtoContract(ImplicitFields=ImplicitFields.AllPublic)]) - however, the current (incomplete) work-in-progress offers POCO support without attributes.


    If you are talking about individual objects:

    There are fairly simple things you can do here with Expression in .NET 3.5; build a dynamic Expression based on reflection, and call .Compile(). MiscUtil has this already:

    DestType clone = PropertyCopy<DestType>.CopyFrom(original);
    

    With .NET 2.0/3.0 (without Expression) you might consider HyperDescriptor for similar purposes.

    0 讨论(0)
  • 2020-12-02 14:13

    I have written three deep clone methods for .NET some time ago:

    • One uses the well-known BinaryFormatter technique (though I tweaked it so that objects do not need to be serializable in order to be cloned). This was by far the slowest.

    • For the second I used pure reflection. It was at least 6 times faster than cloning with the BinaryFormatter. This one could also be used on Silverlight and the .NET Compact Framework.

    • The third one uses Linq Expression Trees (for runtime MSIL generation). It is 60 times faster than the BinaryFormatter technique but has a setup time of approximately 2 milliseconds for the first time each class is encountered.

    Logarithmic scale illustrating cloning performance

    The horizontal axis shows the number of objects cloned (though each cloned object includes several nested objects).

    The BinaryFormatter is labeled "Serialization" in the chart. The data series "Reflection" is a custom one that copies fields via GetField()/SetField().

    I published all three cloning methods as Open Source here:

    http://blog.nuclex-games.com/mono-dotnet/fast-deep-cloning/

    0 讨论(0)
  • 2020-12-02 14:14

    Well! you could write your own Clone Method wich you could specify to ignore or include properties by its attributes. My new library in the link down, uses reflection and FieldInfo to clone the object recursively. i have added it to CodeProject so you will have access to its code soon which you could modify it to your needs.

    Try it out its very fast and clean, you will love it.
    https://www.nuget.org/packages/FastDeepCloner/1.0.1
    or
    PM> Install-Package FastDeepCloner

    0 讨论(0)
  • 2020-12-02 14:25

    There are a lot of libraries that do this operation. You can see benchmark results here:

    In short words, if you need peformance, do it manually, it really faster. Also, some libraries allows to peform shallow cloning (by the question, it is good variant for you), which is faster. And do not use BinaryFormatter if you need any performance.

    Also, @frakon mentions that Expressions trees have same speed as IL Emit, it is slightly incorrect. Expressions Tree is slightly slower, but it can be used in partially trusted app.

    Manual 13ms

    DeepCloner (IL Emit) 167ms

    DeepCloner (Expressions) 267ms

    CloneExtensions (Expressions) 560ms

    NClone 901ms

    Clone.Behave! 8551ms

    GeorgeCloney 1996ms

    Nuclex.Cloning n/a (Crashed)

    FastDeepCloner 1882ms

    BinaryFormatter 15000ms

    0 讨论(0)
提交回复
热议问题