User Tag List

Resultados 1 al 13 de 13

Tema: Herencia y envío http a WebApis

  1. #1

    Fecha de ingreso
    Sep 2005
    Mensajes
    15,202
    Mencionado
    247 Post(s)
    Tagged
    1 Tema(s)
    Agradecer Thanks Given 
    675
    Agradecer Thanks Received 
    1,847
    Thanked in
    Agradecido 1,264 veces en [ARG:2 UNDEFINED] posts

    Herencia y envío http a WebApis

    Buenas a todos:

    Necesito que me echéis un cable, porque no termino de entender bien esto, y sé que por aquí hay más de un experto que sabe más que yo del tema.
    Tengo un programa en C# que envía datos a una WebApi en el mismo lenguaje. El caso es que los datos que envío son de este estilo: tengo artículos, que contienen una lista de lotes, y cada tipo tiene una clase heredada:

    Código:
    public class Batch { protected int id; }
    
    public class DerivedBatch : Batch { public int otroId; }
    
    public class Item
    {
        protected int itemId;
        protected List<Batch> lista;
    }
    
    public class DerivedItem : Item { public string color; }
    Bien, llegado el momento, quiero enviar un DerivedItem, pero para la lista en realidad guardo una serie de DerivedBatch. Aprovecho la herencia para no crear una clase diferente y reaprovechar código (todo esto es un ejemplo extremadamente simplificado).
    Cuando envío los datos:
    Código:
    HttpClient client;
    ...
    client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
    HttpContent content = new StringContent(JsonConvert.SerializeObject(myItem), System.Text.Encoding.UTF8, "application/json");
    HttpResponseMessage response = await client.PostAsync(_url, content);
    He comprobado que se mandan todos los campos de DerivedBatch en el JSON. Sin embargo, en la WebApi:

    Código:
    [Route("api/item/add")]
    public HttpResponseMessage PostAddItem(DerivedItem item)
    {
        if (item.list[0] is DerivedBatch) doStuff();
    }
    La comprobación siempre devuelve "false", es decir, que no lee la lista como una lista de DerivedBatch, sino como una lista de Batch a secas, y hacer un cast tipo:

    Código:
    (DerivedBatch)item.list[0]
    Lanza una excepción porque no se puede convertir Batch en DerivedBatch.
    No sé si hay alguna forma de indicar a la WebApi que el contenido de la lista es de tipo DerivedBatch o no.

    Hasta ahora, la única solución que se me ha ocurrido (y perdón si hago algo horrible) es la de convertir la lista en tipo virtual, y redeclararla en DerivedItem:

    Código:
    public class Batch { protected int id; }
    
    public class DerivedBatch : Batch { public int otroId; }
    
    public class Item
    {
        protected int itemId;
        protected virtual List<Batch> lista;   //<----
    }
    
    public class DerivedItem : Item
    {
        public new List<DerivedBatch> lista;    //<----
        public string color;
    }
    Porque no me deja usar "override" si el tipo del dato es diferente al que sobreescribe. Lo he comprobado, y funciona, pero no me gusta tener código mal escrito y quiero saber cuál sería la forma más correcta de hacer esto.

    ¿Algún entendido en HTML HTTP o en C#... o en cualquier lenguaje orientado a clases, sabe cómo hacer esto?
    Última edición por Drumpi; 03/11/2020 a las 20:25
    PROYECTOS REALIZADOS: FrikiMusic, Motor Scroll Tileado v3.2, Venturer2X (GP2X/WIZ), Echo, Screen Break Time
    PROYECTOS EN MARCHA (algunos): Bennu GP2X: 95% (necesito ayuda) ¡Antes de Halloween!: 92% SpaceH2H: 8%

  2. #2

    Fecha de ingreso
    Nov 2005
    Ubicación
    Excartagenero
    Mensajes
    23,651
    Mencionado
    276 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    5,993
    Agradecer Thanks Received 
    5,820
    Thanked in
    Agradecido 3,793 veces en [ARG:2 UNDEFINED] posts
    Entradas de blog
    1
    No entiendo nada de lo que dices, pero HTML no es un lenguaje eh!!

  3. #3

    Fecha de ingreso
    Sep 2005
    Mensajes
    15,202
    Mencionado
    247 Post(s)
    Tagged
    1 Tema(s)
    Agradecer Thanks Given 
    675
    Agradecer Thanks Received 
    1,847
    Thanked in
    Agradecido 1,264 veces en [ARG:2 UNDEFINED] posts
    Cita Iniciado por josepzin Ver mensaje
    No entiendo nada de lo que dices, pero HTML no es un lenguaje eh!!
    Wikipedia disiente:
    https://es.wikipedia.org/wiki/HTML
    Y el propio nombre también: HyperText Markup Language

    Pero coñas aparte, cierto, la última frase he metido la pata (ahora la edito), quería decir HTTP, y no refiriéndome a él como lenguaje, sino como protocolo de transmisión de datos. Quería decir, si alguien entiende de C#, Java o cualquier otro lenguaje orientado a clases u OOP equivalente que me pueda ayudar, que lo haga.

    PD: acabo de averiguar que no necesito declarar en la clase base la lista como virtual, sólo el new en la derivada ya sobreescribe el dato... pero sigo sin estar seguro de que sea el camino.
    PROYECTOS REALIZADOS: FrikiMusic, Motor Scroll Tileado v3.2, Venturer2X (GP2X/WIZ), Echo, Screen Break Time
    PROYECTOS EN MARCHA (algunos): Bennu GP2X: 95% (necesito ayuda) ¡Antes de Halloween!: 92% SpaceH2H: 8%

  4. #4

    Fecha de ingreso
    Nov 2005
    Ubicación
    Excartagenero
    Mensajes
    23,651
    Mencionado
    276 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    5,993
    Agradecer Thanks Received 
    5,820
    Thanked in
    Agradecido 3,793 veces en [ARG:2 UNDEFINED] posts
    Entradas de blog
    1
    A mi no me preguntes, yo soy un usuario de objetos creados por otros.

  5. #5

    Fecha de ingreso
    Mar 2007
    Ubicación
    Barna
    Mensajes
    10,341
    Mencionado
    93 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    368
    Agradecer Thanks Received 
    1,791
    Thanked in
    Agradecido 944 veces en [ARG:2 UNDEFINED] posts
    Cuidado que no sé si te he entendido bien, y por otro lado te estoy dando mi opinión que es tan válida como la de cualquier otro.

    Cita Iniciado por Drumpi Ver mensaje
    Porque no me deja usar "override" si el tipo del dato es diferente al que sobreescribe.
    Creo que es lo esperado. Si una clase tiene una variable de tipo X, una subclase no puede cambiar el tipo de esa variable. A lo mejor hay algún lenguaje que lo permita, pero me parecería feísimo. Estoy casi seguro que los grandes lenguajes no permiten ir cambiando tipos alegremente y si lo permiten me indignaré mucho.

    Lo que haces, definir una variable como "virtual" y ya veremos más tarde qué es, es una posibilidad que tampoco me gusta pero al menos me gusta más que cambiar tipos. Así que veamos la siguiente solución.

    acabo de averiguar que no necesito declarar en la clase base la lista como virtual, sólo el new en la derivada ya sobreescribe el dato
    Esta es la solución que me gusta: la subclase no cambia el tipo, sino que hace un new de un subtipo del otro tipo. Vaya lío. Para que me entiendas: DerivedBatch es también un Batch, así que puedes asignarla a una variable de tipo Batch sin necesidad de conversiones. Me parece la manera más elegante y perfectamente válida.

    Código:
    public class Item
    {
        protected int itemId;
        protected virtual List<Batch> lista;
    }
    
    public class DerivedItem : Item
    {
        public string color;
    
        public DerivedItem () {
            lista = new List<DerivedBatch>()
        } 
    }
    (no recuerdo si la sintaxis C# es así, ya me entenderás)
    Última edición por juanvvc; 04/11/2020 a las 01:05
    "Todo es absolutamente falso, salvo alguna cosa"

  6. El siguiente usuario agradece a juanvvc este mensaje:

    Drumpi (04/11/2020)

  7. #6

    Fecha de ingreso
    Sep 2005
    Mensajes
    15,202
    Mencionado
    247 Post(s)
    Tagged
    1 Tema(s)
    Agradecer Thanks Given 
    675
    Agradecer Thanks Received 
    1,847
    Thanked in
    Agradecido 1,264 veces en [ARG:2 UNDEFINED] posts
    Bueno, mi intención no es, en realidad, cambiar el tipo, sino que cuando envíe el dato mediante HTTP, la WebApi la recoja y me siga identificando el DerivedBatch que he metido en "lista" como DerivedBatch, y no me haga una conversión a Batch y pierda el dato "otroID", como me estaba pasando. Como digo, si intentaba hacer casting a DerivedBatch, me lanzaba una excepción porque no reconocía el tipo como tal.
    La pega de mi solución es que, según el debugger, se generan dos variables "lista", una a null y otra con la lista de DerivedBatch, y cuando se consulta, toma la lista de DerivedBatch, como debe ser. Funcionar funciona... pero creo que no es la solución correcta.

    Entiendo más o menos lo que quieres hacer, juanvvc (no te preocupes, me han hecho tragar muchísimas sintaxis diferentes, no me asustaría ni el pseudocódigo), pero el problema que hay es que C# no te deja asignar una lista de DerivedBatch a una lista de Batch. Añadir una instancia de DerivedBatch a una lista de Batch, y que mantenga el tipo, no hay pega, pero lo que es la List en sí está muy fuertemente tipada, y ese constructor te va a lanzar una excepción por tipo no válido.

    Es más, creo que lo que he hecho funciona porque las List no se consideran variables, en el sentido más estricto del término, sino más bien una "interfaz" o una "clase", no sé exactamente el termino a usar. Según la documentación, las variables no admiten polimorfismo (al final encontré el palabro).
    https://docs.microsoft.com/es-es/dot...s/polymorphism

    Pero como digo, mi problema no es si sustituir la lista o no, es que me reconozca lo que le envío bien al otro lado del cable.
    PROYECTOS REALIZADOS: FrikiMusic, Motor Scroll Tileado v3.2, Venturer2X (GP2X/WIZ), Echo, Screen Break Time
    PROYECTOS EN MARCHA (algunos): Bennu GP2X: 95% (necesito ayuda) ¡Antes de Halloween!: 92% SpaceH2H: 8%

  8. #7

    Fecha de ingreso
    Feb 2004
    Ubicación
    Madrid
    Mensajes
    22,749
    Mencionado
    226 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    2,240
    Agradecer Thanks Received 
    1,902
    Thanked in
    Agradecido 1,185 veces en [ARG:2 UNDEFINED] posts
    A ver si te he entendido bien, quieres hacer una clase padre que luego las hijas cada una tengan una lista que herede de Batch?
    para eso puedes usar genéricos! El padre puede tener la lista asi:
    Código:
    public List<T> lista : where T is Batch;
    y luego los hijos pueden usar la clase que sea. Eso o hacer override, pero habiendo genéricos no hay necesidad de hacer overrides
    Lo que no se si he entendido al 100% tu problema y lo mismo esta solucion no es válida para lo que quieres.

  9. #8

    Fecha de ingreso
    Sep 2005
    Mensajes
    15,202
    Mencionado
    247 Post(s)
    Tagged
    1 Tema(s)
    Agradecer Thanks Given 
    675
    Agradecer Thanks Received 
    1,847
    Thanked in
    Agradecido 1,264 veces en [ARG:2 UNDEFINED] posts
    Lo de usar genéricos lo tengo que mirar bien, porque hasta ahora, todos los intentos de usarlos me han dado error. No sé si es que no entiendo la sintaxis o que no he dado con el tutorial adecuado.

    Pero mi problema base es que yo uso Item en todo el programa, y todos los Item han usado Batch hasta ahora.
    Ahora me ha llegado una mejora y resulta que para un apartado concreto tengo un DerivedItem que añade propiedades (en este caso es que le hemos añadido el color), y tiene su versión de los Batch (el DeriveBatch añade un identificador de tipo de artículo, para saber si es una herramienta o una prenda, por ejemplo).
    Para no cambiar tooooooodo el código, ni añadir un campo que sólo usa el 10% del programa, quiero usar polimorfismo. Pero cuando mando el DerivedBatch a la WebApi dentro de la lista, esta recoge un Batch, y no sé cómo decirle a la WebApi que es un DerivedBatch, no puedo obtener el identificador de tipo de artículo y el cast me da una excepción porque no reconoce que el dato es un DerivedBatch, según ella, es un Batch a secas.

    También podría añadir el nuevo campo directamente al Batch y quitarme de líos, pero no sé si eso sería correcto, tener una variable (que en la realidad es una lista de datos) y su get/set cuando sólo se va a usar en un pequeño apartado.
    Y me interesa aprender cómo funciona esto por si en un futuro me hiciera falta.
    PROYECTOS REALIZADOS: FrikiMusic, Motor Scroll Tileado v3.2, Venturer2X (GP2X/WIZ), Echo, Screen Break Time
    PROYECTOS EN MARCHA (algunos): Bennu GP2X: 95% (necesito ayuda) ¡Antes de Halloween!: 92% SpaceH2H: 8%

  10. #9

    Fecha de ingreso
    Feb 2004
    Ubicación
    Madrid
    Mensajes
    22,749
    Mencionado
    226 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    2,240
    Agradecer Thanks Received 
    1,902
    Thanked in
    Agradecido 1,185 veces en [ARG:2 UNDEFINED] posts
    Cita Iniciado por Drumpi Ver mensaje
    Lo de usar genéricos lo tengo que mirar bien, porque hasta ahora, todos los intentos de usarlos me han dado error. No sé si es que no entiendo la sintaxis o que no he dado con el tutorial adecuado.

    Pero mi problema base es que yo uso Item en todo el programa, y todos los Item han usado Batch hasta ahora.
    Ahora me ha llegado una mejora y resulta que para un apartado concreto tengo un DerivedItem que añade propiedades (en este caso es que le hemos añadido el color), y tiene su versión de los Batch (el DeriveBatch añade un identificador de tipo de artículo, para saber si es una herramienta o una prenda, por ejemplo).
    Para no cambiar tooooooodo el código, ni añadir un campo que sólo usa el 10% del programa, quiero usar polimorfismo. Pero cuando mando el DerivedBatch a la WebApi dentro de la lista, esta recoge un Batch, y no sé cómo decirle a la WebApi que es un DerivedBatch, no puedo obtener el identificador de tipo de artículo y el cast me da una excepción porque no reconoce que el dato es un DerivedBatch, según ella, es un Batch a secas.

    También podría añadir el nuevo campo directamente al Batch y quitarme de líos, pero no sé si eso sería correcto, tener una variable (que en la realidad es una lista de datos) y su get/set cuando sólo se va a usar en un pequeño apartado.
    Y me interesa aprender cómo funciona esto por si en un futuro me hiciera falta.
    vale pues en ese caso o bien haces la variable virtual, o bien usas un genérico que espera algo de tipo Batch , creo que no tienes mucha más opción. Lo de añadir el campo al Batch suena un poco guarrería si no se va a usar en todos lados

    EDIT: tb veo ahora otra cosa. Ojo con los override y los new que no son lo mismo. Si pones new estás diciendo que es una variable completamente diferente. Si pones override estás diciendo que es la misma pero qu ecambia la implementación. Sigo pensando que yo tiraría por genéricos y a tomar por saco xD

  11. El siguiente usuario agradece a ^MiSaTo^ este mensaje:

    Drumpi (04/11/2020)

  12. #10

    Fecha de ingreso
    Sep 2005
    Mensajes
    15,202
    Mencionado
    247 Post(s)
    Tagged
    1 Tema(s)
    Agradecer Thanks Given 
    675
    Agradecer Thanks Received 
    1,847
    Thanked in
    Agradecido 1,264 veces en [ARG:2 UNDEFINED] posts
    Cita Iniciado por ^MiSaTo^ Ver mensaje
    Ojo con los override y los new que no son lo mismo. Si pones new estás diciendo que es una variable completamente diferente. Si pones override estás diciendo que es la misma pero qu ecambia la implementación. Sigo pensando que yo tiraría por genéricos y a tomar por saco xD
    Sí, lo he visto en la documentación sobre polimorfismo, en el enlace que he puesto en el sexto mensaje.
    Por desgracia, no puedo usar "override" porque en Item, lista es de tipo List<Batch>, y la que quiero meter en DerivedItem es de tipo List<DerivedBatch>, y me da un error indicando que no son del mismo tipo, sólo me admite "new".

    Le echaré de nuevo un vistazo a genéricos, pero es que en cuanto pongo List<T> me dice que el tipo T es desconocido, y los tutoriales que he encontrado no dicen mucho más.
    Gracias por tu sugerencia
    PROYECTOS REALIZADOS: FrikiMusic, Motor Scroll Tileado v3.2, Venturer2X (GP2X/WIZ), Echo, Screen Break Time
    PROYECTOS EN MARCHA (algunos): Bennu GP2X: 95% (necesito ayuda) ¡Antes de Halloween!: 92% SpaceH2H: 8%

  13. #11

    Fecha de ingreso
    Feb 2004
    Ubicación
    Madrid
    Mensajes
    22,749
    Mencionado
    226 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    2,240
    Agradecer Thanks Received 
    1,902
    Thanked in
    Agradecido 1,185 veces en [ARG:2 UNDEFINED] posts
    Cita Iniciado por Drumpi Ver mensaje
    Sí, lo he visto en la documentación sobre polimorfismo, en el enlace que he puesto en el sexto mensaje.
    Por desgracia, no puedo usar "override" porque en Item, lista es de tipo List<Batch>, y la que quiero meter en DerivedItem es de tipo List<DerivedBatch>, y me da un error indicando que no son del mismo tipo, sólo me admite "new".

    Le echaré de nuevo un vistazo a genéricos, pero es que en cuanto pongo List<T> me dice que el tipo T es desconocido, y los tutoriales que he encontrado no dicen mucho más.
    Gracias por tu sugerencia
    En tu caso puede que esté bien poner new en cualquier caso. Es que sin ver todo el código y el caso de uso bien pues no lo entiendo al 100% aun sorry.
    Aún así te recomiendo que mires los genéricos no para este caso pero para que lo tengas en cuenta para otra vez que te pueda hacer falta porque son muy muy utiles.

  14. #12

    Fecha de ingreso
    Sep 2005
    Mensajes
    15,202
    Mencionado
    247 Post(s)
    Tagged
    1 Tema(s)
    Agradecer Thanks Given 
    675
    Agradecer Thanks Received 
    1,847
    Thanked in
    Agradecido 1,264 veces en [ARG:2 UNDEFINED] posts
    Puf, como veas todo el código, te querrás morir (y mira que intento ser ordenado y pulcro ). Sólo te diré que ninguno de los juegos que he hecho hasta ahora tiene tanto código, y sólo el editor de mapas de tiles iguala a esto en complejidad
    Es que tampoco sé cuánto puedo contar del programa, así que por eso cojo ejemplos inventados. Como mucho, que es una APP para un mozo de almacén, y la WebApi que intermedia entre el móvil y el ERP.

    Y sí, le voy a dar un vistazo porque quizás con eso y herencia me podría haber ahorrado la mitad del código... aunque no sé si literalmente o no, una de las cosas que me he dado cuenta con los años es que intentar usar un sistema demasiado genérico para hacer muchas cosas, al final, es una pesadilla para mantenerlo, tanto por la cantidad de código a la que afecta un pequeño cambio, como para hacer la traza de un error, así que hay que usarlo con prudencia.
    PROYECTOS REALIZADOS: FrikiMusic, Motor Scroll Tileado v3.2, Venturer2X (GP2X/WIZ), Echo, Screen Break Time
    PROYECTOS EN MARCHA (algunos): Bennu GP2X: 95% (necesito ayuda) ¡Antes de Halloween!: 92% SpaceH2H: 8%

  15. #13

    Fecha de ingreso
    Feb 2004
    Ubicación
    Madrid
    Mensajes
    22,749
    Mencionado
    226 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    2,240
    Agradecer Thanks Received 
    1,902
    Thanked in
    Agradecido 1,185 veces en [ARG:2 UNDEFINED] posts
    Cita Iniciado por Drumpi Ver mensaje
    Puf, como veas todo el código, te querrás morir (y mira que intento ser ordenado y pulcro ). Sólo te diré que ninguno de los juegos que he hecho hasta ahora tiene tanto código, y sólo el editor de mapas de tiles iguala a esto en complejidad
    Es que tampoco sé cuánto puedo contar del programa, así que por eso cojo ejemplos inventados. Como mucho, que es una APP para un mozo de almacén, y la WebApi que intermedia entre el móvil y el ERP.

    Y sí, le voy a dar un vistazo porque quizás con eso y herencia me podría haber ahorrado la mitad del código... aunque no sé si literalmente o no, una de las cosas que me he dado cuenta con los años es que intentar usar un sistema demasiado genérico para hacer muchas cosas, al final, es una pesadilla para mantenerlo, tanto por la cantidad de código a la que afecta un pequeño cambio, como para hacer la traza de un error, así que hay que usarlo con prudencia.
    Tranquilo si siendo de curro te entiendo que no puedas dar muchos más detalles

    A ver no puedes hacer algo totalmente generico ni nada generico, siempre es un punto entre medias. Lo dificil es dar con ese punto pero a más experiencia en algo, más facil es llegar a él.
    Si tienes compis trabajando en lo mismo o parecido pide hacer code reviews que de eso se aprende muchísimo!

Etiquetas para este tema

Permisos de publicación

  • No puedes crear nuevos temas
  • No puedes responder temas
  • No puedes subir archivos adjuntos
  • No puedes editar tus mensajes
  •