2010-03-07 37 views
21

Tôi có một tình huống mà tôi đang tải một bản ghi rất không chuẩn hóa từ Excel. Tôi kéo vào mỗi hàng và tạo ra các đối tượng từ mỗi hàng một. mỗi hàng có thể chứa một công ty và/hoặc một khách hàng.C# hợp nhất hai đối tượng với nhau tại thời gian chạy

Vấn đề của tôi là nhiều hàng có thể có cùng một đối tượng, vì vậy tôi có thể đã tạo ra nó. Tôi so sánh để xem liệu nó đã có trong danh sách chưa. Nếu vậy tôi cần hợp nhất hai đối tượng để đảm bảo tôi không thu được bất kỳ thông tin mới nào từ hàng thứ hai.

vậy:

company - client - address - phone 
---------------------------------------- 
mycompany -   - myaddress - 
mycompnay - myclient -   - myphone 

nên hàng đầu tiên sẽ tạo ra một đối tượng công ty với một địa chỉ của "myaddress". Hàng thứ hai sẽ tạo đối tượng công ty khác (theo quy tắc của tôi là cùng một công ty với tên giống nhau), điều này cũng có tham chiếu khách hàng và số điện thoại.

Vì vậy, tôi sẽ biết chúng giống nhau nhưng cần phải đảm bảo tất cả dữ liệu được hợp nhất thành một đối tượng.

Hiện tại tôi đang tạo lớp tiện ích lấy cả hai đối tượng, (một là tên chính và phần còn lại sẽ được hợp nhất, vì vậy có ưu tiên nếu có xung đột), nó đi qua từng biến và gán giá trị nếu có cái nào. Đây là một tấm hơi nặng và tôi hy vọng có thể có một số tiện ích mà tôi có thể sử dụng để thực hiện công việc thủ công cho tôi.

Ví dụ đã được đơn giản hóa vì có một vài biến số hợp lý khác, một số loại cơ bản và các biến khác là các mục phức tạp hơn.

+0

Bạn có chắc chắn luôn có tối đa 2 đối tượng cần hợp nhất không? Điều gì sẽ xảy ra nếu cùng một cột/thuộc tính được xác định hai lần? Nghe có vẻ nguy hiểm chỉ để bỏ qua một !? – Achim

+0

Cách họ đang lặp lại thông qua các bộ sưu tập của tôi tại thời điểm tôi sẽ hợp nhất trong mỗi trận đấu được tìm thấy. Về lý thuyết, có thể có nhiều kết quả phù hợp thông qua bộ sưu tập, nhưng mỗi lần hợp nhất sẽ được thực hiện mỗi lần. Nếu người dùng đã đưa dữ liệu xấu vào để tôi phải mất một số giá trị vì nhiều lĩnh vực tôi không thể nhìn thấy dù sao xung quanh đó. – Jon

Trả lời

37

Phản ánh sẽ hoạt động. Một cái gì đó như:

public static void MergeWith<T>(this T primary, T secondary) { 
    foreach (var pi in typeof(T).GetProperties()) { 
     var priValue = pi.GetGetMethod().Invoke(primary, null); 
     var secValue = pi.GetGetMethod().Invoke(secondary, null); 
     if (priValue == null || (pi.PropertyType.IsValueType && priValue.Equals(Activator.CreateInstance(pi.PropertyType)))) { 
      pi.GetSetMethod().Invoke(primary, new object[]{secValue}); 
     } 
    } 
} 
+7

Chung và trang nhã. Nhưng bằng cách nào đó nó làm cho một cơn rùng mình lạnh run chạy dọc sống lưng của tôi. – CesarGon

+0

Mũ rất đẹp cho bạn thưa bạn! ;-) – BlackTea

+1

Vì lý do nào đó, 'priValue == Activator.CreateInstance (pi.PropertyType)' trả về false cho các kiểu giá trị. Thay vào đó, 'priValue.Equals (Activator.CreateInstance (pi.PropertyType))' tạo ra kết quả chính xác. – Mrchief

1

Thử tạo bảng băm dựa trên chuỗi. Sử dụng một nối của một tập con của các trường mà bạn coi là trình kích hoạt cho bản ghi trùng lặp làm khóa. Hàm hashtable sẽ không cho phép các bản sao để bạn có thể sử dụng lỗi này làm trình kích hoạt để thực hiện xử lý tiếp theo.

0

Nếu không biết nhiều hơn về môi trường và yêu cầu của bạn, điều này có thể không sử dụng được. Nhưng nếu bạn có một số loại cơ sở dữ liệu back-end có sẵn (thậm chí miễn phí phía máy khách), bạn có thể lưu trữ dữ liệu trong một bảng và sử dụng câu lệnh SQL Merge để cập nhật dữ liệu. Thao tác hợp nhất sẽ thêm hoặc cập nhật bản ghi nếu cần. Một kích hoạt có thể tinh chỉnh thêm hoạt động. Đây là một giải pháp khá nặng, nhưng nếu bạn đã có một số DBMS trong hỗn hợp, nó có thể là một phương pháp dễ thực hiện nó.

3

Tôi muốn chia nhỏ phần này: chia và chinh phục.

Trước tiên, hãy đọc tất cả các đối tượng trong một danh sách lớn.

Trong bước thứ hai, hãy chọn danh sách riêng biệt bằng cách sử dụng khóa chính của bạn, ví dụ: tên công ty. Từ danh sách riêng biệt, sử dụng mục (bản chính) có số trường lớn nhất được đặt. Sau đó, lặp qua tất cả các trường chưa có trong master và hợp nhất các giá trị của chúng. LINQ sẽ giúp bạn rất nhiều trong nhiều bước này mà không cần phải viết các thuật toán phức tạp theo cách thủ công.

Điều này cho phép tùy chỉnh logic dễ dàng sau này, ví dụ: nếu bạn có một bộ 'khóa chính' khác để nói hoặc nếu bạn muốn so sánh đặc biệt của các trường cụ thể.

0

Khi bạn truy xuất dữ liệu từ Excel, không cần tạo đối tượng cho mỗi hàng.Trong thực tế, bạn có thể muốn đi đến một hình thức trung gian mà đọc tất cả các hàng lên phía trước, sau đó nó tạo ra các đối tượng từ đó. Giải pháp của Kibbey sử dụng các bảng băm có thể hoạt động ở đây.

+0

Xin chào, xin lỗi tôi đã đơn giản hóa ví dụ của tôi một cách dễ dàng. Tôi đọc toàn bộ xls vào một datatable thẳng off sau đó tạo ra một cấu trúc của mỗi hàng để làm xử lý của tôi trên thay vì đối phó với nó trực tiếp. – Jon

2

Tôi đã thử Merge Two Objects into an Anonymous Type bởi Kyle Finley và nó hoạt động hoàn hảo.

Với TypeMerger việc sáp nhập cũng đơn giản như

var obj1 = new {foo = "foo"};

var obj2 = new {bar = "bar"};

var mergedObject = TypeMerger.MergeTypes(obj1 , obj2);

Đó là nó, bạn có đối tượng sáp nhập, ngoài ra, có một điều khoản để bỏ qua đặc tính cụ thể quá.

+1

Không gian tên nào là TypeMerger? Tôi giả sử đó là một đối tượng tùy chỉnh bởi vì tôi không thể tìm thấy nó ngay cả bằng cách tìm kiếm google. –

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