2010-03-05 3 views
13

Ich bin ziemlich neu (ok, REALLy neu) Generika, aber ich liebe die Idee von ihnen. Ich werde auf einem Blick ein paar Dropdown-Listen zu haben und ich würde eine generische Art und Weise wie eine Liste von Objekten zu nehmen und es zu einer Liste von SelectListItemsWie generische IEnumerable <SelectListItem> Extension-Methode schreiben

zu konvertieren Was ich habe jetzt:

public static IEnumerable<SelectListItem> ToSelectListItems(
    this IEnumerable<SpecificObject> items, long selectedId) 
    { 
     return 
      items.OrderBy(item => item.Name) 
      .Select(item => 
        new SelectListItem 
        { 
         Selected = (item.Id == selectedId), 
         Text = item.Name, 
         Value = item.Id.ToString() 
        }); 
    } 

das Problem ist, würde ich brauche diesen Code für jeden Drop-down zu wiederholen, wie die Objekte verschiedene Bereiche haben, die die Text Eigenschaft des SelectListItem

hier vertreten ist, was ich erreichen möchte:

public static IEnumerable<SelectListItem> ToSelectListItem<T>(this IEnumerable<T> items, string key, string value, int SelectedId) { 
    // I really have no idea how to proceed from here :(
} 

Antwort

20

Nun, Sie so etwas tun könnte:

public static IEnumerable<SelectListItem> ToSelectListItems(
    this IEnumerable<T> items, 
    Func<T,string> nameSelector, 
    Func<T,string> valueSelector, 
    Func<T,bool> selected) 
{ 
    return items.OrderBy(item => nameSelector(item)) 
      .Select(item => 
        new SelectListItem 
        { 
         Selected = selected(item), 
         Text = nameSelector(item), 
         Value = valueSelector(item) 
        }); 
} 
+0

Abbrechen das, musste ToSelectListItems :) – Dan

+1

Wie würde ich dies nennen und insbesondere den 'ausgewählten' Delegaten verwenden? – Dan

+0

Sehr schöne Lösung! – Samuel

3

Damit dies so geschrieben zu arbeiten, Ihre Art T müssen einige Schnittstelle implementieren, die Name und Id Eigenschaften bietet:

public interface ISelectable 
{ 
    string Name { get; } 
    int Id { get; } 
} 

In diesem Ort können Sie tun:

public static IEnumerable<SelectListItem> ToSelectListItems<T>(this IEnumerable<T> items, long selectedId) 
    where T : ISelectable 
{ 
    return 
     items.OrderBy(item => item.Name) 
     .Select(item => 
       new SelectListItem 
       { 
        Selected = (item.Id == selectedId), 
        Text = item.Name, 
        Value = item.Id.ToString() 
       }); 
} 

Dies ist erforderlich, um die Eigenschaften Name und Id innerhalb Ihrer Erweiterungsmethode zu verwenden ... Sie könnten stattdessen ein anderes Mittel zum Empfangen dieser (dh: Weitergabe von Stellvertretern) bereitstellen, aber das kann oder m Erhöhen Sie nicht die Wartungskosten in Ihrem Szenario.

+0

Freund, mit dieser Methode, wie würde ich benutze es ? Sieht sauberer aus als andere Antworten. Vielen Dank ! –

8

Sie könnten Delegierte übergeben, um die Vergleiche und das Property Retrieval durchzuführen. Etwas wie folgt aus:

public static IEnumerable<SelectListItem> ToSelectListItem<T>(this IEnumerable<T> items, 
    int selectedId, Func<T,int> getId, Func<T, string> getName, 
    Func<T, string> getText, Func<T, string> getValue) 
{ 
    return 
     items.OrderBy(item => getName(item)) 
     .Select(item => 
       new SelectListItem 
       { 
        Selected = (getId(item) == selectedId), 
        Text = getText(item), 
        Value = getValue(item) 
       }); 
} 

Dann würden Sie es wie so verwenden:

var selected = specificObjects.ToSelectListItem(10, s => s.Id, s=> s.Name, s => s.Name, s => s.Id.ToString()); 
+0

Sie würden auch einen getName-Delegaten benötigen (nach Brunos Antwort) - der item.Name-Verweis in der OrderBy-Klausel wird derzeit nicht kompiliert. – itowlson

+0

Hmm, ich möchte sowohl diese als auch die nächsten Fragen als Antworten markieren :). Beide sind genau das, wonach ich suche! – Dan

+0

@itowlson - danke, das habe ich verpasst. –

Verwandte Themen