2012-06-25 30 views
5

Tôi có một số IEnumerable<KeyValuePair<string,string>>, từ đó tôi muốn một đối tượng ẩn danh có khóa làm tên thuộc tính và giá trị làm giá trị thuộc tính.Chuyển đổi KeyValuePair thành loại ẩn danh trong truy vấn LINQ

Tôi đã thử các biểu thức lựa chọn khác nhau (không ai trong số đó thậm chí được biên dịch ...) và cách tiếp cận sử dụng ExpandoObject (xem bên dưới), nhưng không thành công. Có cách nào tốt để làm điều này? Nếu có thể, tôi muốn tránh lặp lại rõ ràng hơn trong bộ sưu tập (nghĩa là thực hiện tất cả bằng câu lệnh LINQ của một số loại).

Đây là những gì tôi đã thử cho đến nay. Tôi hy vọng nó cũng làm rõ những gì tôi đang cố gắng để làm:

var kvps = getProps(); // returns IEnumerable<KeyValuePair<string,string>> 

dynamic o = new ExpandoObject(); 
foreach (var kvp in kvps) 
{ 
    o.Add(kvp); 
} 

Đây là OK lúc biên dịch, nhưng khi chạy tôi nhận được một YSOD nêu 'System.Dynamic.ExpandoObject' không chứa một định nghĩa cho ' Thêm ' - Tôi đoán nó hoạt động tại thời gian biên dịch vì o là động, do đó trình biên dịch không thể biết liệu phương thức .Add() đã được thêm vào nó vì nó đã được khởi tạo hay chưa. Điều kỳ lạ là, trên MSDN documenation page for ExpandoObject.Add() được liệt kê là một trong một số "phương pháp giao diện được triển khai rõ ràng". Không cần thiết cho tôi để có được điều này thành một đối tượng năng động - Tôi chỉ cần có một cái gì đó có tên và giá trị thuộc tính theo các khóa và giá trị của các cặp khóa-giá trị.

Cập nhật: Vâng, điều này thật đáng xấu hổ. Hóa ra đây cũng là vấn đề XY.

Tôi đang cố gắng hiển thị điều này với JSON bằng cách sử dụng các tính năng tích hợp của ASP.NET MVC, bằng cách đơn giản trả về Json(data) trong bộ điều khiển của tôi. Những câu trả lời tất cả các hoạt động rất tốt để làm những gì tôi lần đầu tiên hỏi, nhưng khi tôi vượt qua đối tượng này như data tôi vẫn không nhận được những gì tôi muốn:

// What I get: 
[ 
    { Key: 'firstkey', Value: 'FirstValue' }, 
    { Key: 'secondKey', Value: 'secondValue' } 
] 

// What I want: 
{ firstKey: 'FirstValue', secondKey: 'secondValue' } 

Rõ ràng, một ExpandoObject với các thuộc tính có liên quan bổ sung không cắt nó - nó được đúc để một cuốn từ điển trước khi render ...

+1

Và có, tôi đã thấy [câu hỏi này] (http://stackoverflow.com/questions/4685575/converting-a-keyvaluepair-collection-in-to-anonymous-type). Đó thực sự là một [vấn đề XY] (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem), đã được giải quyết mà không giúp tôi. –

Trả lời

4

ExpandoObject thực hiện một cách rõ ràng IDictionary<string, object> - vì vậy bạn cần phải cast nó vào một đầu tiên:

var kvps = getProps(); 
dynamic o = new ExpandoObject(); 
var dict = o as IDictionary<string, object>; 
foreach (var kvp in kvps) 
{ 
    dict.Add(kvp.Key, kvp.Value); 
} 

Bây giờ bạn có thể sử dụng o như bạn mong chờ:

var example = o.YourKey; 

Tôi đang cố gắng kết xuất điều này với JSON bằng cách sử dụng các tính năng tích hợp của ASP.NET MVC, bằng cách đơn giản trả về Json (dữ liệu) trong bộ điều khiển của tôi.

Thú vị.

Để làm điều đó, bạn sắp xếp theo thứ tự từ điển, không phải là ExpandoObject. Trình serializer của MVC 3 đã làm điều đó với một từ điển.Tất cả những gì bạn phải làm là chuyển đổi IEnumerable<KeyValuePair<string, object>> thành từ điển:

var kvps = getProps(); 
var dictionary = kvps.ToDictionary(k => k.Key, v => v.Value); 
return Json(dictionary, JsonRequestBehavior.AllowGet); //take out allow get if you don't need it. 

Không cần động lực.

+0

Cảm ơn! Tuy nhiên, tôi đã hơi nhanh để xây dựng vấn đề của mình - vui lòng xem cập nhật của tôi ... –

+0

@TomasLycken Đã cập nhật. – vcsjones

+0

Tuyệt vời! Cảm ơn rất nhiều! =) –

6

bạn cần phải sử dụng ExpandoObject như một IDictionary<string, object> khi populating nó:

var kvps = getProps(); // returns IEnumerable<KeyValuePair<string,string>> 

IDictionary<string, object> o = new ExpandoObject(); 
foreach (var kvp in kvps) 
{ 
    // Or use Add(kvp.Key, kvp.Value), if you want 
    o[kvp.Key] = kvp.Value; 
} 

dynamic d = o; 
// Now you can use the properties 
+0

Điều này cho tôi một lỗi biên dịch trên dòng đầu tiên ('IDictionary o = new ExpandoObject();'), nhưng vì đó là bạn tôi giả định trình biên dịch là sai. Tôi đoán nó nghĩ rằng nó nên là 'IDictionary ' - Tôi sẽ ngay lập tức nói với bạn rằng bạn đã nói để làm điều đó theo cách này. –

+0

Hiện tại, nó hoạt động =) –

+0

... nhưng không hoàn toàn. Vui lòng xem cập nhật của tôi. –

1

tôi nghĩ rằng bạn phải đúc tượng expando của bạn để IDictionary và gọi Thêm (string, object)

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