2012-02-14 15 views
5

Estoy tratando de encontrar una forma genérica para asignar valores a una propiedad dictada por una expresión lambda, mire el código de ejemplo a continuación, ¿cómo sería la firma de ConverToEntities aspecto del método y cómo se llamaría?Método genérico para establecer el valor de una propiedad utilizando expresiones/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

¿Cuál es la lista Tho? Supongo que lo que realmente quieres es una lista pública estática ConvertToEntities ... ¿o no? –

+0

ConvertToEntities es un intento de un método genérico; es sintaxis incorrecta, estoy buscando hacer este método genérico; –

+0

Dadas las soluciones, el '.Select' provisto con .Net es menos código ... –

Respuesta

4

Ok. Lo más cerca que pude conseguir fue esto:

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(); 
     } 
    } 

Esto funciona.

Tengo la sensación de que está un poco confundido con lo que realmente quiere como el tipo de devolución. Sería genial poder especificar lo que queremos en la llamada al método o smth. Por ejemplo:

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

Esto nos proporciona más flexibilidad en el tipo de devolución. Pero ya que estamos haciendo esto utilizando extensiones, supongo que esto no es posible porque tenemos que saber qué tipo estamos ampliando:

this List<long> entities, 

Niza cuestión.

EDIT Código de sugerencia de sugerencia.

+0

¡¡¡Eso es excelente !! gran solución; muchas gracias :-) –

+0

gracias hombre. y gracias, fue un buen acertijo para nosotros los novatos –

1

Creo que @Zortkun tiene razón sobre el tipo de devolución. Prueba el followin:

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

y que llamarían la siguiente manera:

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

Usted puede hacer algo como esto, pero no es tan simple o agradable. La lambda p => p.DataId le ofrece el acceso de acceso de la propiedad. Se podría utilizar Expression s para obtener el organismo, pero probablemente es mejor usar el colocador directamente en la lambda:

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

La aplicación se vería así:

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(); 
} 
Cuestiones relacionadas