2012-02-14 7 views
5

Sto cercando di trovare un modo generico per assegnare valori a una proprietà dettato da un'espressione lambda, guardare il codice riportato di seguito, come sarebbe la firma per i ConverToEntities aspetto del metodo e come si chiamerebbe?metodo generico per impostare il valore di una proprietà utilizzando le espressioni/lambda

static void Main() 
{ 
    List<long> ids = new List<long> {1, 2, 3}; 

    //Non generic way 
    List<Data> dataItems = ids.ConvertToDataItems(); 

    //Generic attempt!! 
    List<Data> differntDataItems = 
     ids.ConvertToEntities<Data>(p => p.DataId); 
} 

public class Data 
{ 
    public long DataId; 
    public string Name; 
} 

public static class ExtensionMethods 
{ 
    public static List<Data> ConvertToDataItems(this List<long> dataIds) 
    { 
     return dataIds.Select(p => new Data { DataId = p }).ToList(); 
    } 

    public static List<T> ConvertToEntities<TProp>(
     this List<long> entities, Func<TProp> lambdaProperty) 
    { 
     return entities.Select(p => new T {lambdaProperty}).ToList(); 
    } 
} 
+0

Qual è List tho? .. Immagino che quello che vuoi sia statico pubblico Elenco ConvertToEntities ... o no? –

+0

I ConvertToEntities è un tentativo di un metodo generico; è sintatticamente sbagliato, sto cercando di rendere questo metodo generico; –

+0

Date le soluzioni, il '.Select' fornito con .Net è meno codice ... –

risposta

4

Ok. Il più vicino che ho potuto ottenere è stato questo:

class Program 
    { 
     static void Main(string[] args) 
     { 
      List<long> ids = new List<long> { 1, 2, 3 }; 

      //Non generic way 
      List<Data> dataItems = ids.ConvertToDataItems(); 

      //Generic attempt!! 

      Func<long, Data> selector = (p => new Data { DataId = p }); 
      List<Data> differntDataItems = ids.ConvertToEntities<Data>(selector); 
     } 
    } 

    public class Data 
    { 
     public long DataId; 
     public string Name; 
    } 

    public static class ExtensionMethods 
    { 
     public static List<Data> ConvertToDataItems(this List<long> dataIds) 
     { 
      return dataIds.Select(p => new Data { DataId = p }).ToList(); 
     } 

     public static List<TProp> ConvertToEntities<TProp>(this List<long> entities, Func<long, TProp> selector) 
     { 
      return entities.Select(selector).ToList(); 
     } 
    } 

Questo funziona.

Ho la sensazione che hai urself un po 'confuso con quello che realmente vuole, come il tipo di ritorno. Sarebbe bello poter specificare ciò che vogliamo nel metodo call o smth. Ad esempio:

public static List<TProp> ConvertToEntities<T, TProp>(List<T> entities, Func<T, TProp> selector) 
    { 
     return entities.Select(selector).ToList(); 
    } 

Ciò ci fornisce più flessibilità sul tipo di reso. Ma dal momento che stiamo facendo questo utilizzando le estensioni, Presumo che ciò è impraticabile, perché abbiamo bisogno di sapere che tipo stiamo estendendo:

this List<long> entities, 

Nizza domanda.

EDIT Codice suggerimento correzione.

+0

Questo è eccellente !! ottima soluzione; grazie mille :-) –

+0

grazie amico. e grazie, è stato un bel indovinello per noi neofiti –

1

credo @Zortkun è di destra circa il tipo di ritorno. Prova il followin:

public static List<TProp> ConvertToEntities<TProp>(
    this List<long> entities, Func<long, TProp> lambdaProperty) 
{ 
    return entities.Select(lambdaProperty).ToList(); 
} 

e si sarebbe chiamata come segue:

ids.ConvertToEntities<Data>(p => new Data { DataId = p }); 
2

Si può fare qualcosa di simile, ma non è così semplice o piacevole. Il lambda p => p.DataId vi dà l'accesso get della proprietà. Si potrebbe utilizzare Expression s per ottenere il setter, ma probabilmente è meglio usare il setter direttamente nella lambda:

List<Data> differntDataItems = 
    ids.ConvertToEntities<long, Data>((p, i) => p.DataId = i); 

L'implementazione sarebbe simile a questa:

public static List<T> ConvertToEntities<TProp, T>(
    this List<TProp> dataIds, Action<T, TProp> lambdaProperty) 
    where T : new() 
{ 
    return dataIds.Select(
     p => 
     { 
      var result = new T(); 
      lambdaProperty(result, p); 
      return result; 
     }).ToList(); 
}