You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否基于Protobuf-Net实现泛型复制构造方法?(避免反射且不新建对象)

Using Protobuf-Net for Generic Deep Copy to an Existing Target Object

Great question! You absolutely can create a generic deep copy method with protobuf-net that populates an existing target object without relying on slow reflection. The secret is leveraging protobuf-net's built-in Merge functionality, which is optimized for exactly this scenario—plus, protobuf-net uses IL generation (not reflection) after the first call to your generic method, so you get excellent performance.

Step 1: Mark Your Class for Protobuf-Net Serialization

First, you need to tell protobuf-net which members of your class to serialize. Add the [ProtoContract] attribute to your class and [ProtoMember] to each property you want copied:

using ProtoBuf;

[ProtoContract]
public class Person {
    [ProtoMember(1)]
    public Int32 Id { get; set; }
    [ProtoMember(2)]
    public String FirstName { get; set; }
    [ProtoMember(3)]
    public Int32 Age { get; set; }
    [ProtoMember(4)]
    public String Name { get; set; }
}

Step 2: Implement the Generic Copy Method

Use Serializer.Merge<T> to copy data from the source to the target object. This method handles serialization to an in-memory stream and then merges the data into the existing target—no new object creation required, no reflection overhead after the first call:

using System.IO;
using ProtoBuf;

public static void DeepCopyConstructor<T>(T source, T target) where T : class
{
    if (source == null || target == null)
        throw new ArgumentNullException(source == null ? nameof(source) : nameof(target));

    using (var stream = new MemoryStream())
    {
        // Serialize the source object to the stream
        Serializer.Serialize(stream, source);
        // Reset the stream position to the start
        stream.Position = 0;
        // Merge the stream data into the target object
        Serializer.Merge(stream, target);
    }
}

How This Works (and Why It Avoids Reflection)

  • On the first call to DeepCopyConstructor<T> for a specific type T, protobuf-net generates optimized IL code for serializing/deserializing that type. This is done once, at runtime.
  • All subsequent calls reuse this generated IL code—no reflection is involved, making this method far faster than reflection-based copy approaches.
  • The Merge operation overwrites the target object's properties with values from the source, effectively performing a deep copy (since protobuf-net handles nested objects recursively).

Example Usage

Test the method with your Person class to verify it works:

// Create a source person with sample data
var source = new Person { Id = 1, FirstName = "John", Age = 30, Name = "John Doe" };
// Create an empty target person (or one with existing values you want to overwrite)
var target = new Person { Id = 2, FirstName = "Jane" };

// Run the copy method
DeepCopyConstructor(source, target);

// Now target has all the source's values:
// target.Id == 1, target.FirstName == "John", target.Age == 30, target.Name == "John Doe"

Key Notes

  • Required Attributes: Don't skip the [ProtoContract] and [ProtoMember] attributes—protobuf-net needs these to know which members to process. You can customize member numbers (the integer in [ProtoMember(X)]) as needed, just ensure they're unique per class.
  • Null Handling: The method includes null checks to avoid runtime errors—adjust this if your use case allows nulls.
  • Nested Objects: If your class contains other complex objects (e.g., a List<Address>), just mark those classes with protobuf-net attributes too, and the deep copy will work recursively.

内容的提问来源于stack exchange,提问作者Franki1986

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:56:19