2009-10-24 43 views
35

Có thể trong C# để tạo System.Collections.Generic.Dictionary<TKey, TValue> trong đó TKey là lớp không điều kiện và TValue - một lớp ẩn danh với một số thuộc tính, ví dụ: tên cột cơ sở dữ liệu và tên được bản địa hóa.Từ điển giá trị là loại ẩn danh trong C#

Something như thế này:

new { ID = 1, Name = new { Column = "Dollar", Localized = "Доллар" } } 
+0

Rất tương tự (với LINQ): [Một danh sách chung của lớp vô danh] (http://stackoverflow.com/questions/612689/a-generic-list- of-anonymous-class) – nawfal

+0

.Chọn (...). AsEnumerable(). ToDictionary (k => k.id, v => v làm đối tượng) làm việc cho tôi. Biến của tôi là Từ điển Ravi

+0

@Ravishankar: Bạn không cần 'AsEnumerable()' ở đây, có thể là nhất. Nó không thêm bất cứ điều gì trên đầu trang của 'Chọn()'. – abatishchev

Trả lời

38

Bạn không thể tuyên bố như vậy một loại từ điển trực tiếp (có kludges nhưng đây là để giải trí và mới lạ mục đích duy nhất), nhưng nếu dữ liệu của bạn đến từ một IEnumerable hoặc nguồn IQueryable, bạn có thể có được một bằng cách sử dụng toán tử LINQ ToDictionary và nhô ra chìa khóa cần thiết và giá trị (nặc danh đánh máy) từ các yếu tố trình tự:

var intToAnon = sourceSequence.ToDictionary(
    e => e.Id, 
    e => new { e.Column, e.Localized }); 
16

Như itowlsonsaid, bạn không thể tuyên bố như một con thú, nhưng bạn có thể thực sự tạo một:

static IDictionary<TKey, TValue> NewDictionary<TKey, TValue>(TKey key, TValue value) 
{ 
    return new Dictionary<TKey, TValue>(); 
} 

static void Main(string[] args) 
{ 
    var dict = NewDictionary(new {ID = 1}, new { Column = "Dollar", Localized = "Доллар" }); 
} 

Nó không rõ tại sao bạn muốn thực sự muốn sử dụng mã như thế này.

+10

Tại sao? Tôi có thể nghĩ ra một số lý do. Đây là một. Hãy xem xét ví dụ một từ điển được sử dụng để ghi nhớ một hàm n-ary, nói một hàm của bốn đối số int. Trong phiên bản tiếp theo của CLR, bạn chỉ cần sử dụng 4-tuple, nhưng trong C# 3, bạn có thể tạo một từ điển kiểu ẩn danh {int, int, int, int}, xong, không cần phải tự định nghĩa loại tuple. –

+9

Tôi hiện có một mục nhập khác cho phần "bàn chải có danh tiếng" trên trang chủ cá nhân của tôi! :-) –

3

Bạn có thể làm một bữa ăn

public static class ObjectExtensions 
{ 
    /// <summary> 
    /// Turn anonymous object to dictionary 
    /// </summary> 
    /// <param name="data"></param> 
    /// <returns></returns> 
    public static IDictionary<string, object> ToDictionary(this object data) 
    { 
     var attr = BindingFlags.Public | BindingFlags.Instance; 
     var dict = new Dictionary<string, object>(); 
     foreach (var property in data.GetType().GetProperties(attr)) 
     { 
      if (property.CanRead) 
      { 
       dict.Add(property.Name, property.GetValue(data, null)); 
      } 
     } 
     return dict; 
    } 
} 
+0

Ý tưởng hay. Ngoài ra bạn có thể làm cho nó chung chung: 'public static IDictionary ToDictionary (dữ liệu đối tượng này) {}' – abatishchev

3

tôi nghĩ ASP.NET MVC không lối ra vào thời điểm câu hỏi này đã được thực hiện. Nó chuyển đổi các đối tượng ẩn danh thành từ điển trong nội bộ.

Chỉ cần xem ví dụ HtmlHelper class. Phương thức dịch các đối tượng thành từ điển là AnonymousObjectToHtmlAttributes. Nó là specifc để MVC và trả về một RouteValueDictionary, tuy nhiên.

Nếu bạn muốn một cái gì đó chung chung hơn, hãy thử này:

public static IDictionary<string,object> AnonymousObjectToDictionary(object obj) 
{ 
    return TypeDescriptor.GetProperties(obj) 
     .OfType<PropertyDescriptor>() 
     .ToDictionary(
      prop => prop.Name, 
      prop => prop.GetValue(obj) 
     ); 
} 

Một advatages intersting thực hiện này là nó trả về một từ điển rỗng cho null đối tượng.

Và đây là một phiên bản generic:

public static IDictionary<string,T> AnonymousObjectToDictionary<T>(
    object obj, Func<object,T> valueSelect 
) 
{ 
    return TypeDescriptor.GetProperties(obj) 
     .OfType<PropertyDescriptor>() 
     .ToDictionary<PropertyDescriptor,string,T>(
      prop => prop.Name, 
      prop => valueSelect(prop.GetValue(obj)) 
     ); 
} 
+0

Cảm ơn bạn đã cho biết điều đó! Những bất lợi của phương pháp như vậy tôi có thể đặt tên là sử dụng sự phản ánh. – abatishchev

+0

@abatishchev Tôi nghĩ rằng không thể giải quyết vấn đề mà không phản ánh. Tôi không chắc chắn, nhưng việc đọc các thuộc tính với TypeDescriptor có thể hiệu quả hơn so với thông thường .GetType(). GetProperties(). BTW, tôi đã sử dụng ILSpy trên HtmlHelper và nó gần như hoàn toàn giống nhau. – jpbochi

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