2011-11-18 45 views
8

Tôi có hai đối tượng cùng loại và cần phải sao chép các giá trị thuộc tính từ một đối tượng này sang đối tượng khác. Có hai tùy chọn:Sao chép các thuộc tính đối tượng: phản chiếu hoặc tuần tự hóa - nhanh hơn?

  1. Sử dụng phản ánh, điều hướng qua các thuộc tính của đối tượng đầu tiên và sao chép giá trị.

  2. Sắp xếp lại đối tượng đầu tiên và deserialize một bản sao.

Cả hai làm việc theo yêu cầu của tôi, câu hỏi nào là tốt nhất tôi nên sử dụng trong điều kiện tốc độ (chi phí)?

Ví dụ

class Person 
{ 
    public int ID { get; set; } 
    public string Firsthand { get; set; } 
    public string LastName { get; set; } 
    public int Age { get; set; } 
    public decimal Weight { get; set; } 
} 

Cần để sao chép giá trị tài sản từ Person p1 để Person p2.

Đối với mẫu đơn giản này - phương pháp nào nhanh hơn?

Cập nhật

Đối serialization tôi sử dụng ObjectCopier gợi ý ở đây: Deep cloning objects

Đối với phản ánh tôi sử dụng mã này:

foreach (PropertyInfo sourcePropertyInfo in copyFromObject.GetType().GetProperties()) 
{ 
    PropertyInfo destPropertyInfo = copyToObject.GetType().GetProperty(sourcePropertyInfo.Name); 

    destPropertyInfo.SetValue(
     copyToObject, 
     sourcePropertyInfo.GetValue(copyFromObject, null), 
     null); 
} 
+2

Làm thế nào về autoMapper http://automapper.org/ hoặc chỉ Clone() thực hiện công việc? – roundcrisis

+0

Tại sao bạn không thể làm điều đó với nhiệm vụ bình thường? –

+0

@Miau, Đây có vẻ là một hệ thống sao chép tài sản phức tạp, nhờ liên kết, rất thú vị. Nhưng đối với nhu cầu của tôi hiện tại tôi yêu cầu nó được đơn giản, do đó, AutoMapper sẽ là một canon cho trường hợp này tôi nghĩ. Nhưng tôi chắc chắn sẽ kiểm tra và sử dụng nó cho các nhiệm vụ phức tạp. –

Trả lời

10

Tất cả phụ thuộc vào nội dung bạn muốn sao chép và loại trình xử lý tuần tự bạn định sử dụng. Điều với serializers là, một số trong số chúng có thể thực sự sử dụng sự phản chiếu như cơ chế cơ bản của các đối tượng xây dựng.

Chỉnh sửa # 1: Theo như tôi biết, BinaryFormatter được sử dụng bởi lớp học của bạn sử dụng phản ánh để thực hiện công việc của mình. Vì vậy, câu hỏi là, bạn có thể viết mã phản chiếu tùy chỉnh tốt hơn (nhanh hơn?) Cho các loại của bạn hơn là Microsoft đã làm cho kịch bản chung không?

Chỉnh sửa # 2: Ngoài sự tò mò, tôi đã chạy thử nghiệm đơn giản. BinaryFormatter so với phản ánh về mặt biểu diễn bản sao cạn. đang suy nghĩ tôi đã sử dụng có thể được nhìn thấy ở đây:

var newPerson = Activator.CreateInstance<Person>(); 
var fields = newPerson.GetType().GetFields(BindingFlags.Public 
    | BindingFlags.Instance); 
foreach (var field in fields) 
{ 
    var value = field.GetValue(person); 
    field.SetValue(newPerson, value); 
} 

kết quả là gì so với ObjectCopier lớp học mà bạn đang sử dụng? Phản ánh dường như thực hiện nhanh hơn 7 lần so với mã tuần tự hóa. Tuy nhiên, điều này áp dụng cho Person lớp học với các trường công khai. Đối với các thuộc tính, sự khác biệt vẫn đáng chú ý, nhưng nó chỉ nhanh gấp 2 lần.

Tôi giả định sự khác biệt xuất phát từ thực tế là BinaryFormatter cần sử dụng luồng, giới thiệu thêm chi phí bổ sung. Tuy nhiên, đây chỉ là giả định của tôi, mà có thể là xa sự thật.

Mã nguồn cho chương trình thử nghiệm Tôi đã sử dụng có thể được tìm thấy here. Bất kỳ ai được chào đón đến điểm sai sót và các vấn đề có thể với nó :-)


Sidenote
Như với tất cả "Tôi đã tự hỏi ..." tiêu chuẩn, tôi đề nghị bạn mang nó theo một hạt Muối. Tối ưu hóa như vậy chỉ nên được thực hiện khi hiệu suất của chúng thực sự trở thành một vấn đề.

+0

Tôi có các lớp đơn giản với các kiểu nguyên thủy, chẳng hạn như int, string, etc ... Tôi sử dụng serializer được đề xuất ở đây: http://stackoverflow.com/questions/78536/cloning-objects-in-c-sharp Các loại lớp được cung cấp bởi mã bên ngoài. –

+0

@net_prog: kiểm tra chỉnh sửa của tôi. Tôi đã chạy thử nghiệm đơn giản cho lớp của bạn bằng cả hai phương pháp. –

+0

Cảm ơn bạn, đây là những gì tôi đang tìm kiếm. Tôi thực sự muốn lớp học được với các thuộc tính, không phải các lĩnh vực, tôi đã sửa mẫu. Nhưng ngay cả trong trường hợp này, sự phản chiếu nhanh hơn tôi có thể thấy. –

0

serialization nhị phân rất nhanh tôi sử dụng nó rất nhiều cho loại sự cố này

Deep cloning objects

+0

Để serialization tôi sử dụng ObjectCopier từ thread đó, nó có nhanh hơn phản xạ không? –

+3

@net_prog làm thế nào để bạn nghĩ rằng 'BinaryFormatter' (serializer trong' ObjectCopier') được dữ liệu của nó? Gợi ý: nó bắt đầu bằng "r" và có vẻ như "lệch". –

0

Nếu bạn đang sao chép thuộc tính trong thời gian chạy, phản chiếu sẽ là câu trả lời. Tôi sẽ đi serialization nếu nó không phải trong thời gian chạy. Serialization vs Reflection xem xét điều này một lần.

+0

Tôi sao chép vào thời gian chạy. –

+0

Nếu bạn biết các thuộc tính của đối tượng trong thời gian chạy, sự phản ánh sẽ lãng phí thời gian, việc tuần tự hóa sẽ là câu trả lời. Nhưng nếu bạn không biết các thuộc tính của đối tượng trong thời gian chạy, thì phản xạ là giải pháp duy nhất tôi có thể nghĩ đến. – nebula

+0

Nếu bạn biết các thuộc tính, tại sao serialization đột nhiên tốt hơn so với phản xạ? Không chắc chắn có ý nghĩa ... –

7

Cuối cùng, serializers có mục đích chung (chẳng hạn như BinaryFormatter, qua ObjectCopier) đang sử dụng phản ánh. Làm thế nào cũng họ sử dụng nó phụ thuộc vào serializer cụ thể, nhưng luôn luôn có thêm chi phí liên quan nếu bạn đang serializing.

Vì bạn chỉ muốn một bản sao nông, một công cụ như AutoMapper là công cụ phù hợp nhất ở đây; một lần nữa, nó đang sử dụng sự phản chiếu (nhưng tôi hy vọng nó đang làm nó "đúng cách", tức là không thông qua GetValue()/SetValue()), nhưng nó không có chi phí serialization.

Trong trường hợp này, việc tuần tự hóa quá mức; AutoMapper là hoàn toàn hợp lý. Nếu bạn muốn có dòng vô tính, nó sẽ trở nên phức tạp hơn ... việc tuần tự hóa có thể bắt đầu bị cám dỗ. Tôi vẫn có thể sẽ không chọn BinaryFormatter bản thân mình, nhưng tôi rất kén chọn về serialization; p

Nó sẽ tất nhiên là tầm thường sang phải một số cơ bản phản ánh mà không giống nhau qua GetValue() vv, nhưng đó sẽ là chậm . Một tùy chọn thú vị khác ở đây là bạn có thể sử dụng API Expression để tạo máy sao chép đối tượng lúc chạy .... nhưng ... AutoMapper làm mọi thứ bạn cần ở đây, vì vậy có vẻ như nỗ lực dư thừa.

0
void Copy(object copyToObject, object copyFromObject) 
{ 
    BindingFlags flags = BindingFlags.Public | BindingFlags.Instance; 

    FieldInfo[] fields = copyFromObject.GetType().GetFields(flags); 
    for (int i = 0; i < fields.Length; ++i) 
    { 
     BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic 
      | BindingFlags.Static; 
     FieldInfo field = copyFromObject.GetType().GetField(fields[i].Name, bindFlags); 
     FieldInfo toField = copyToObject.GetType().GetField(fields[i].Name, bindFlags); 
     if(field != null) 
     { 
      toField.SetValue(copyToObject, field.GetValue(copyFromObject)); 
     } 
    } 
} 
+0

Mã có thể trả lời câu hỏi. Nhưng bạn sẽ giúp OP nhiều hơn nếu bạn giải thích mã nào và cách giải quyết câu hỏi. – Markus

Các vấn đề liên quan