Convirtiendo los métodos de extensión sobre secuencias de entidades en métodos genéricos

Vamos a realizar un cambio a la biblioteca de clases UtilidadesDigi que hemos ido construyendo en nuestro curso de programación de Digi3D:

Si te fijas en el código de los métodos de extensión UtilidadesSecuenciaEntity.QueTenganElCódigo, UtilidadesSecuenciaEntity.QueTenganElCódigoConComodín, UtilidadesSecuenciaEntity.QueTenganAlgúnCódigo y UtilidadesSecuenciaEntity.QueTenganAlgúnCódigoConComodín:

    public static IEnumerable<Entity> QueTenganElCódigo(this IEnumerable<Entity> secuenciaOriginal, string código)
    {
        return from entidad in secuenciaOriginal
               where entidad.TieneElCódigo(código)
               select entidad;
    }
    public static IEnumerable<Entity> QueTenganElCódigoConComodín(this IEnumerable<Entity> secuenciaOriginal, string código)
    {
        return from entidad in secuenciaOriginal
               where entidad.TieneElCódigoConComodín(código)
               select entidad;
    }
    public static IEnumerable<Entity> QueTenganAlgúnCódigo(this IEnumerable<Entity> secuenciaOriginal, IEnumerable<string> códigos)
    {
        return from entidad in secuenciaOriginal
               where entidad.TieneAlgúnCódigo(códigos)
               select entidad;
    }
    public static IEnumerable<Entity> QueTenganAlgúnCódigoConComodín(this IEnumerable<Entity> secuenciaOriginal, IEnumerable<string> códigos)
    {
        return from entidad in secuenciaOriginal
               where entidad.TieneAlgúnCódigoConComodín(códigos)
               select entidad;
    }

Siempre devuelven una secuencia de IEntity, aunque esa secuencia esté particularizada para un determinado tipo de entidad, y eso deshabilita todos los filtros que se hubieran aplicado antes, como en el siguiente ejemplo:

            var líneasDeMarcoHoja = DigiNG.DrawingFile.OfType<ReadOnlyLine>().QueTenganElCódigo(códigoDelMarco);

Vamos a estudiar que pasa con la línea de código anterior:

  • DigiNG.DrawingFile devuelve una secuencia de IEnumerable<IEntity>.
  • Generamos una secuencia de ReadOnlyLine mediante el método de extensión de Linq: OfType<T>. A partir de este momento tenemos una secuencia: IEnumerable<ReadOnlyLine>.
  • Luego llamamos al método de extensión UtilidadesDigiNG.QueTenganElCódigo que extuende IEnumerable<IEntity> y que devuelve una secuencia: IEnumerable<IEntity>.

Lo que resulta en que al final lo que tenemos es un IEnumerable<IEntity>, y está claro por el contexto que lo que queremos es un IEnumerable<ReadOnlyLine>.

En este caso particular, podríamos haberlo solucionado de la siguiente forma:

            var líneasDeMarcoHoja = DigiNG.DrawingFile.QueTenganElCódigo(códigoDelMarco).OfType<ReadOnlyLine>();

Pero esa no es la solución. Tenemos que modificar nuestros métodos de extensión para que sean genéricos, de forma que si están subclasificando una secuencia de X, que lo que devuelvan sea una secuencia de X y no una secuencia de otra cosa.

Éstos métodos van a extender secuencias de tipos cuya base sea IEntity, así que cuando las convirtamos en métodos genéricos tendrán que tener como restricción que el tipo genérico herede de IEntity.

Veamos cómo quedan nuestros métodos de extensión una vez convertidos en métodos genéricos:

    public static IEnumerable<T> QueTenganElCódigo<T>(this IEnumerable<T> secuenciaOriginal, string código)
        where T : Entity
    {
        return from entidad in secuenciaOriginal
               where entidad.TieneElCódigo(código)
               select entidad;
    }

    public static IEnumerable<T> QueTenganElCódigoConComodín<T>(this IEnumerable<T> secuenciaOriginal, string código)
        where T : Entity
    {
        return from entidad in secuenciaOriginal
               where entidad.TieneElCódigoConComodín(código)
               select entidad;
    }

    public static IEnumerable<T> QueTenganAlgúnCódigo<T>(this IEnumerable<T> secuenciaOriginal, IEnumerable<string> códigos)
        where T : Entity
    {
        return from entidad in secuenciaOriginal
               where entidad.TieneAlgúnCódigo(códigos)
               select entidad;
    }

    public static IEnumerable<T> QueTenganAlgúnCódigoConComodín<T>(this IEnumerable<T> secuenciaOriginal, IEnumerable<string> códigos)
        where T : Entity
    {
        return from entidad in secuenciaOriginal
               where entidad.TieneAlgúnCódigoConComodín(códigos)
               select entidad;
    }

De esta manera estos métodos de extensión devuelven subconjuntos de secuencias sin cambiar su tipo.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s