2012-06-20 16 views
9

Belirtilen birkaç parametreden bir HTML tablosu oluşturmak istiyorum. IEnumerable listesi ve Mesela T. bazı özelliklerini alt kümesi, en bu sınıfın bir listesi var diyelim: Özellikle, benim yönteme geçirmek istediğiniz iki parametre vardırBelirtilen özelliklere sahip genel sınıf listesinden HTML tablosu oluştur

class Person 
{ 
    string FirstName 
    string MiddleName 
    string LastName 
} 

listesinde sahip olduğunu varsayalım İçinde 5 kişi var. Ben oluşturulan tabloyu istediğiniz özellikleri belirtmek için daha iyi bir yolu var eminim

List<Person> people; 
...add people to list 

string HTML = GetMyTable(people, "FirstName", "LastName"); 

: Böyle bir şey yaparak bu sınıfın bir HTML tablosu (veya başka keyfi sınıf) elde edebilmek istiyorum (ya da hangi özelliklerin tablodan çıkarılmasını istiyorum, bu genellikle sınıfın özelliklerinin çoğunu veya tümünü istediğimden daha iyi olurdu), ama nasıl emin olamadım (asla yansıma kullanmıyordum, ama ben tahmin etmek nasıl). Ayrıca, yöntem herhangi bir sınıfın bir listesini kabul etmelidir.

Bunu nasıl gerçekleştireceğiniz konusunda akıllıca fikirler var mı?

cevap

19

Belki böyle bir şey? Sıkı bir döngü içinde performans katil olabilir defalarca fxn.Compile() çağrılması: 2.0--

public static string GetMyTable<T>(IEnumerable<T> list, params Expression<Func<T, object>>[] fxns) 
{ 

    StringBuilder sb = new StringBuilder(); 
    sb.Append("<TABLE>\n"); 

    sb.Append("<TR>\n"); 
    foreach (var fxn in fxns) 
    { 
     sb.Append("<TD>"); 
     sb.Append(GetName(fxn)); 
     sb.Append("</TD>"); 
    } 
    sb.Append("</TR> <!-- HEADER -->\n"); 


    foreach (var item in list) 
    { 
     sb.Append("<TR>\n"); 
     foreach (var fxn in fxns) 
     { 
      sb.Append("<TD>"); 
      sb.Append(fxn.Compile()(item)); 
      sb.Append("</TD>"); 
     } 
     sb.Append("</TR>\n"); 
    } 
    sb.Append("</TABLE>"); 

    return sb.ToString(); 
} 

static string GetName<T>(Expression<Func<T, object>> expr) 
{ 
    var member = expr.Body as MemberExpression; 
    if (member != null) 
     return GetName2(member); 

    var unary = expr.Body as UnaryExpression; 
    if (unary != null) 
     return GetName2((MemberExpression)unary.Operand); 

    return "?+?"; 
} 

static string GetName2(MemberExpression member) 
{ 
    var fieldInfo = member.Member as FieldInfo; 
    if (fieldInfo != null) 
    { 
     var d = fieldInfo.GetCustomAttribute(typeof(DescriptionAttribute)) as DescriptionAttribute; 
     if (d != null) return d.Description; 
     return fieldInfo.Name; 
    } 

    var propertInfo = member.Member as PropertyInfo; 
    if (propertInfo != null) 
    { 
     var d = propertInfo.GetCustomAttribute(typeof(DescriptionAttribute)) as DescriptionAttribute; 
     if (d != null) return d.Description; 
     return propertInfo.Name; 
    } 

    return "?-?"; 
} 

PS

version

var html = GetMyTable(people, x => x.LastName, x => x.FirstName); 

public static string GetMyTable<T>(IEnumerable<T> list,params Func<T,object>[] fxns) 
{ 

    StringBuilder sb = new StringBuilder(); 
    sb.Append("<TABLE>\n"); 
    foreach (var item in list) 
    { 
     sb.Append("<TR>\n"); 
     foreach(var fxn in fxns) 
     { 
      sb.Append("<TD>"); 
      sb.Append(fxn(item)); 
      sb.Append("</TD>"); 
     } 
     sb.Append("</TR>\n"); 
    } 
    sb.Append("</TABLE>"); 

    return sb.ToString(); 
} 
. Bir sözlükte önbelleğe almak daha iyi olabilir.

public static string GetMyTable(IEnumerable list, params string[] columns) 
{ 
    var sb = new StringBuilder(); 
    foreach (var item in list) 
    { 
     //todo this should actually make an HTML table, not just get the properties requested 
     foreach (var column in columns) 
      sb.Append(item.GetType().GetProperty(column).GetValue(item, null)); 
    } 
    return sb.ToString(); 
} 
//used like 
string HTML = GetMyTable(people, "FirstName", "LastName"); 

Veya kullanarak lambda'lar: lambdas ile

public static string GetMyTable<T>(IEnumerable<T> list, params Func<T, object>[] columns) 
{ 
    var sb = new StringBuilder(); 
    foreach (var item in list) 
    { 
     //todo this should actually make an HTML table, not just get the properties requested 
     foreach (var column in columns) 
      sb.Append(column(item)); 
    } 
    return sb.ToString(); 
} 
//used like 
string HTML = GetMyTable(people, x => x.FirstName, x => x.LastName); 

ne oluyor her almak için GetMyTable yöntemine yöntemleri geçiyoruz olduğunu

+0

Örneğin int ve dize seçmeye çalışırsanız ne olur? P 'nesne 'olacak mı, yoksa derleme değil mi? –

+0

@TimS. Teşekkürler cevabı güncelledim. –

+0

"fxn (item)" ın ne yaptığını açıklayabilir misiniz? – birdus

3

Burada iki yaklaşım, birini kullanarak yansımasıdır özelliği. Bu güçlü yazım ve muhtemelen performans gibi yansımalara yarar sağlar.

+0

Yardımın için teşekkürler, Tim. Bunu yapmanın çeşitli yollarını görmekten memnuniyet duyuyorum. – birdus

6

Yaptığım şey buydu ve iyi performans gösterdiği görülüyor.

public static string ToHtmlTable<T>(this List<T> listOfClassObjects) 
    { 
     var ret = string.Empty; 

     return listOfClassObjects == null || !listOfClassObjects.Any() 
      ? ret 
      : "<table>" + 
       listOfClassObjects.First().GetType().GetProperties().Select(p => p.Name).ToList().ToColumnHeaders() + 
       listOfClassObjects.Aggregate(ret, (current, t) => current + t.ToHtmlTableRow()) + 
       "</table>"; 
    } 

    public static string ToColumnHeaders<T>(this List<T> listOfProperties) 
    { 
     var ret = string.Empty; 

     return listOfProperties == null || !listOfProperties.Any() 
      ? ret 
      : "<tr>" + 
       listOfProperties.Aggregate(ret, 
        (current, propValue) => 
         current + 
         ("<th style='font-size: 11pt; font-weight: bold; border: 1pt solid black'>" + 
         (Convert.ToString(propValue).Length <= 100 
          ? Convert.ToString(propValue) 
          : Convert.ToString(propValue).Substring(0, 100)) + "..." + "</th>")) + 
       "</tr>"; 
    } 

    public static string ToHtmlTableRow<T>(this T classObject) 
    { 
     var ret = string.Empty; 

     return classObject == null 
      ? ret 
      : "<tr>" + 
       classObject.GetType() 
        .GetProperties() 
        .Aggregate(ret, 
         (current, prop) => 
          current + ("<td style='font-size: 11pt; font-weight: normal; border: 1pt solid black'>" + 
            (Convert.ToString(prop.GetValue(classObject, null)).Length <= 100 
             ? Convert.ToString(prop.GetValue(classObject, null)) 
             : Convert.ToString(prop.GetValue(classObject, null)).Substring(0, 100) + 
              "...") + 
            "</td>")) + "</tr>"; 
    } 

sadece ToHtmlTable() bir liste Örnek geçmesi kullanmak için:

listesi belgeleri = GetMyListOfDocuments(); var table = documents.ToHtmlTable();

İlgili konular