He preguntado esto pregunta sobre el uso de la Linq método que devuelve un objeto (en Primer lugar, Min, Max, etc) a partir de una colección genérica.
Ahora quiero ser capaz de utilizar linq Excepto() método y no estoy seguro de cómo hacerlo. Tal vez la respuesta está justo en frente de mí, pero creo que necesito ayuda.


Tengo un método genérico que se llena en las fechas que falta de la correspondiente descriptivo, de campo. Este método se declara de la siguiente manera:

public IEnumerable<T> FillInMissingDates<T>(IEnumerable<T> collection, string datePropertyName, string descriptionPropertyName)
    {
       Type type = typeof(T);
       PropertyInfo dateProperty = type.GetProperty(datePropertyName);
       PropertyInfo descriptionProperty = type.GetProperty(descriptionPropertyName);
       ...
    }

Lo que quiero lograr es este. datePropertyName es el nombre de la propiedad de fecha voy a utilizar para llenar mi fecha de huecos (por defecto instancias de objetos para las fechas que no estén ya presentes en la colección). Si yo estuviera tratando con una no-clase genérica, me gustaría hacer algo como esto:

foreach (string description in descriptions)
{
    var missingDates = allDates.Except(originalData.Where(d => d.Description == desc).Select(d => d.TransactionDate).ToList());
...
}

Pero, ¿cómo puedo hacer lo mismo usando el método genérico FillInMissingDates con el dateProperty y descriptionProperty propiedades se resuelve en tiempo de ejecución?

  • Tendrás que nos muestran la definición de su clase genérica (o, al menos, los correspondientes bits) antes de que podamos responder apropiadamente.
  • Noldorin, el tipo de T, como en el FillInMissingDates genérica declaración de método.
  • No estoy seguro de lo que quieres decir. Si no estás restringiendo el tipo genérico T, entonces no se puede garantizar la existencia de la datePropertyName de la propiedad.
  • Lo sentimos, todavía no muy seguro de lo que quieres decir con «hacer lo mismo». En el ejemplo que usted da, usted está utilizando la Excepción de/Donde los métodos. En lo que respecta qué desea hacer la misma cosa?
  • Quiero usar el mismo, Excepto Donde los métodos, pero el nombre de las propiedades sólo se conoce en tiempo de ejecución.
  • ¿Quiere usted decir que le gustaría utilizar una sintaxis como: someCollection.FillInMissingDates(x => x.Campos creationdate, x => x.ItemDescription) ?

5 Comentarios

  1. 3

    Creo que la mejor manera sería definir una interfaz con todas las propiedades que desea utilizar en su método. Tienen las clases que el método puede ser utilizado en implementar esta interfaz. A continuación, utilice un método genérico y restringir el tipo genérico que se derivan de la interfaz.

    Este ejemplo no puede hacer exactamente lo que quieres — llena de fechas para los elementos de la lista corresponde a una descripción, pero es de esperar que se le dará a usted la idea básica.

     public interface ITransactable
     {
         string Description { get; }
         DateTime? TransactionDate { get; }
     }
    
     public class CompletedTransaction : ITransactable
     {
         ...
     }
    
     //note conversion to extension method
     public static void FillInMissingDates<T>( this IEnumerable<T> collection, 
                                               string match,
                                               DateTime defaultDate )
            where T : ITransactable
     {
          foreach (var trans in collection.Where( t => t.Description = match ))
          {
              if (!trans.TransactionDate.HasValue)
              {
                  trans.TransactionDate = defaultDate;
              }
          }
     }

    Deberá emitir su enumeración a ITransactable antes de invocar (al menos hasta que C# 4.0 sale).

     var list = new List<CompletedTransaction>();
    
     list.Cast<ITransactable>()
         .FillInMissingDates("description",DateTime.MinValue);

    Alternativamente, usted podría investigar el uso de Dinámica de LINQ de la VS2008 Muestras colección. Esto le permitirá especificar el nombre de una propiedad si no es consistente entre las clases. Probablemente todavía tiene que utilizar la reflexión para establecer la propiedad, sin embargo.

    • Hola tvanfosson. Gracias por tu respuesta. No me gustaría utilizar una interfaz porque no tienen la capacidad de la interfaz para la definición de la clase. Como he explicado en la pregunta (después de haber editado), estoy usando la reflexión para obtener las propiedades reales basándose en sus nombres. Gracias!
  2. 1

    Usted podría tratar de este enfoque:

    public IEnumerable<T> FillInMissingDates<T>(IEnumerable<T> collection, 
        Func<T, DateTime> dateProperty, Func<T, string> descriptionProperty, string desc)
    {
        return collection.Except(collection
            .Where(d => descriptionProperty(d) == desc))
            .Select(d => dateProperty(d));
    }

    Esto le permite hacer cosas como:

    someCollection.FillInMissingDates(o => o.CreatedDate, o => o.Description, "matching");

    Tenga en cuenta que usted no necesita necesariamente la Except() llamada, y sólo tienen:

    .. Where(d => descriptionProperty(d) != desc)
  3. 0
    foreach (string description in descriptions)
    {    
    var missingDates = allDates.Except<YourClass>(originalData.Where(d => d.Description == desc).Select(d => d.TransactionDate).ToList());
    }

    De hecho, casi toda la extensión de LINQ en C# tiene un genérico de valor posible. (Excepto y Salvo)

    • Eso no es lo que él se está refiriendo a que yo pienso. Él quiere decir que YourClass es genérico, no la Salvo método de extensión. Incluso muestra en su ejemplo el tipo de inferencia que hace innecesario, en su caso.
    • Tienes razón Noldorin. No sé cuál es el nombre de la Descripción de la propiedad (por lo tanto, la descriptionPropertyName parámetro). He añadido más información a la pregunta. Gracias.
  4. 0

    Si vas a identificar la propiedad a la que se accede por un nombre de cadena, entonces usted no necesita el uso de medicamentos genéricos. Su único propósito es de tipo estático de seguridad. Sólo el uso de la reflexión para acceder a la propiedad, y que el método de trabajo en un no-genérico IEnumerable.

    • Esta es, probablemente, más de lo que él está buscando, aunque todavía estoy a la espera de aclaraciones.
  5. 0

    Llegar a Excepción de resultado con múltiples propiedades trabajar con datos personalizados de clase no está permitido.
    Tienes que usar algo como esto: (en msdn 101 ejemplos de LINQ)

    public void Linq53() 
    { 
        List<Product> products = GetProductList(); 
        List<Customer> customers = GetCustomerList(); 
    
        var productFirstChars = 
            from p in products 
            select p.ProductName[0]; 
        var customerFirstChars = 
            from c in customers 
            select c.CompanyName[0]; 
    
        var productOnlyFirstChars = productFirstChars.Except(customerFirstChars); 
    
        Console.WriteLine("First letters from Product names, but not from Customer names:"); 
        foreach (var ch in productOnlyFirstChars) 
        { 
            Console.WriteLine(ch); 
        } 
    }

    Tener la clave, usted puede manejar sus datos de acuerdo 🙂

Dejar respuesta

Please enter your comment!
Please enter your name here