2010-08-10 34 views
12

Để sao chép các giá trị tài sản từ một đối tượng khác, chúng ta thường đạt được với cú pháp sau:Sao chép các giá trị tài sản cho đối tượng khác với C#

ca.pro1 = cb.pro2; 
ca.pro2 = cb.pro2; 

nơi ca và cb là của cùng một lớp.

Có bất kỳ phương pháp đồng bộ hoặc phương pháp tiện ích đơn giản hơn để giúp chúng tôi đạt được hiệu quả tương tự không?

Cảm ơn bạn.

+0

Đây là những gì bạn đang tìm kiếm: [đối tượng Cloning trong C#] (https://stackoverflow.com/questions/ 78536/cloning-objects-in-c) –

Trả lời

3

không thực sự. có một MemberwiseClone() nhưng sao chép tham chiếu trực tiếp nghĩa là bạn sẽ nhận được một tham chiếu đến cùng một đối tượng và điều đó có thể xấu. Bạn có thể triển khai giao diện ICloneable và sử dụng giao diện đó để sao chép sâu. Tôi thích làm cho phương thức Clone() của riêng tôi mặc dù vì giao diện ICloneable trả về một đối tượng cần được cast.

+3

Tôi sẽ không bận tâm với ICloneable, nó là không thể thực hiện đúng bởi vì giao diện không cho phép người gọi để chỉ ra những gì ông có nghĩa là bằng cách "nhân bản". –

+0

tôi tin rằng tiêu chuẩn thực tế là một bản sao sâu, nhưng điều đó cũng đi với những gì tôi đã nói về cách tạo ra phương pháp sao chép của riêng bạn, để an toàn hơn, v.v. –

10

Đây là một chức năng mà tôi đã sử dụng để sao chép các thành viên giữa các mô hình trong ASP.NET MVC. Trong khi bạn tìm kiếm mã hoạt động cho cùng một loại, mã này cũng sẽ hỗ trợ các loại khác có cùng thuộc tính.

Nó sử dụng phản xạ nhưng theo cách gọn gàng hơn. Hãy coi chừng Convert.ChangeType: bạn có thể không cần nó; bạn có thể kiểm tra loại thay vì chuyển đổi.

public static TConvert ConvertTo<TConvert>(this object entity) where TConvert : new() 
{ 
    var convertProperties = TypeDescriptor.GetProperties(typeof(TConvert)).Cast<PropertyDescriptor>(); 
    var entityProperties = TypeDescriptor.GetProperties(entity).Cast<PropertyDescriptor>(); 

    var convert = new TConvert(); 

    foreach (var entityProperty in entityProperties) 
    { 
     var property = entityProperty; 
     var convertProperty = convertProperties.FirstOrDefault(prop => prop.Name == property.Name); 
     if (convertProperty != null) 
     { 
      convertProperty.SetValue(convert, Convert.ChangeType(entityProperty.GetValue(entity), convertProperty.PropertyType)); 
     } 
    } 

    return convert; 
} 

Do đây là một phương pháp khuyến nông, việc sử dụng rất đơn giản:

var result = original.ConvertTo<SomeOtherType>(); 
+0

PropertyDescriptor.SetValue không hoạt động cho tôi, phải sử dụng var convertProperties = typeof (TConvert) .GetProperties(); - trong đó cung cấp cho bạn một List of PropertyInfo thay vì PropertyDescriptor's – MHolzmayr

+0

Trong Hindsight: "không hoạt động" có nghĩa là, mã đã chạy, nhưng nó không đặt bất kỳ giá trị nào, ví dụ bool properties, b/c chúng có các bộ định riêng (D ' Oh!). – MHolzmayr

14
public static void CopyPropertiesTo<T, TU>(this T source, TU dest) 
{ 
    var sourceProps = typeof (T).GetProperties().Where(x => x.CanRead).ToList(); 
    var destProps = typeof(TU).GetProperties() 
      .Where(x => x.CanWrite) 
      .ToList(); 

    foreach (var sourceProp in sourceProps) 
    { 
     if (destProps.Any(x => x.Name == sourceProp.Name)) 
     { 
      var p = destProps.First(x => x.Name == sourceProp.Name); 
      if(p.CanWrite) { // check if the property can be set or no. 
       p.SetValue(dest, sourceProp.GetValue(source, null), null); 
      } 
     } 

    } 

} 
3

Nếu tôi không nhầm với những gì là cần thiết, cách để dễ dàng đạt được copy giá trị tài sản giữa hai các phiên bản hiện tại (thậm chí không cùng loại) là sử dụng Automapper.

  1. tạo cấu hình bản đồ
  2. và sau đó gọi .map (soure, mục tiêu)

Chừng nào bạn giữ tài sản trong cùng một loại và trong quy ước đặt tên giống nhau, tất cả đều phải làm việc.

Ví dụ:

MapperConfiguration _configuration = new MapperConfiguration(cnf => 
      { 
       cnf.CreateMap<SourceType, TargetType>(); 
      }); 
var mapper = new Mapper(_configuration); 
maper.DefaultContext.Mapper.Map(source, target) 
1
public static TTarget Convert<TSource, TTarget>(TSource sourceItem) 
     { 
      if (null == sourceItem) 
      { 
       return default(TTarget); 
      } 

      var deserializeSettings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace, }; 

      var serializedObject = JsonConvert.SerializeObject(sourceItem, deserializeSettings); 

      return JsonConvert.DeserializeObject<TTarget>(serializedObject); 
     } 

sử dụng:

promosion = YourClass.Convert<Promosion, PromosionExtension>(existsPromosion); 
Các vấn đề liên quan