c# - una - lanzar objeto hijo como padre
mdi container c# (8)
Necesito poder convertir una instancia de un objeto secundario a una instancia del objeto principal.
public class Parent
{
public string name{get;set;}
}
public class Child : Parent{}
var myClass = new Child()
(Parent)myClass
//this doesnt seem to work and the object still has childs type.
¿Hay otra forma de lanzarlo?
Gracias
El problema es que el serializador xml serializa el objeto con tipo secundario como elemento raíz. Realmente no quiero pasar mi tipo de destino hasta el serializador. ¿hay una mejor manera? - Jules
No he trabajado mucho con la serialización, pero supongo que necesitarás modificar tu definición de "cómo me serializo" en el elemento hijo para escribir como si fuera un padre.
Si realmente desea tener una instancia de "Padre", deberá crear un nuevo Padre y copiar todos los valores del Niño al Padre. (No haría esto si tiene muchos de ellos, pero si no tiene tantos, no debería ser un problema). La forma más sencilla de hacerlo sería crear un constructor de copias en Padre. Sería un constructor que toma un padre como parámetro y copia los valores (nombre en este caso, y supongo que puede haber omitido otros) del parámetro a sí mismo. Luego, puede crear un nuevo Padre, pasar el Niño como parámetro (ya que un Niño es un Padre, no se necesita conversión / conversión) y escupirá una instancia real del Padre.
Acabo de encontrar una variante del problema, creo que tengo una solución no basada en serialización.
Al igual que el OP, tengo Clase B que hereda de la Clase A, y necesito B.GetType (). Nombre para regresar como si fuera la Clase A.
En la Clase B, debe anular GetType () para devolver .GetType (). BaseType
De esa manera B.GetType () siempre se verá como A.GetType ()
Como eso es bastante duro, y todas mis clases heredan de mi propia baseClass estándar, agregaré una propiedad llamada TypeName a la baseClass que devuelve esto.GetType (). Name
Luego, en mi única clase especial en la que quiero que parezca que es el padre, la anularé para devolver esto.GetType (). BaseType.Name
Luego, en mi código, haré referencia a .TypeName en lugar de hacer .GetType (). Nombre directamente cuando necesito el "enmascaramiento" especial del nombre de tipo de la clase para activarlo. Dado que solo estoy usando .GetType () en El área en la que necesito ignorar esta clase infantil es bastante limpia para mi propio uso.
Eso debería funcionar.
Pero sospecho que por la forma en que has escrito tu código, ¿no has capturado el objeto de conversión en una nueva variable? Prueba esto:
var myClass = new Child()
var myClassAsParent = (Parent)myClass;
// myClassAsParent still has the type "Child", but can be accessed as if it were a Parent.
Editar Según algunos de los comentarios que ha estado dejando, creo que malinterpreta un aspecto fundamental de la mayoría de los lenguajes de programación. Es este: el Tipo de un objeto no puede cambiar . Un objeto que se creó como un objeto secundario siempre será un objeto Child
.
Casting no cambia el tipo de un objeto. El lanzamiento cambia la forma en que el resto del programa "ve" el objeto. Cambia la interfaz del objeto, si lo desea. Entonces, si lanzas un objeto Child
a un tipo de Parent
, el resto del programa piensa que se trata de un tipo de Parent
, pero en realidad se trata de un tipo de Child
, es decir, usar una analogía muy mala, vestida con la ropa de su padre.
En resumen, Casting no hace lo que crees que hace.
Estoy cerca de cinco años tarde aquí, pero ...
Puedes usar AutoMapper para resolver tu problema.
Simplemente defina un mapeo entre las clases padre e hijo. El mapa más simple hará. En la clase donde define sus asignaciones:
CreateMap<Child, Parent>();
Entonces, en cualquier punto de tu código, podrías hacer:
Child child = new Child();
Parent parent = Mapper.Map<Parent>(child);
Y su objeto parent
será un Parent
puro sin ninguna de las propiedades del objeto child
.
Como han dicho otros, lanzar un objeto conservará su tipo. Eso solo cambia el puntero. Pero AutoMapper crea una nueva instancia del tipo de destino y copia los valores del parámetro a la instancia del tipo de destino, haciendo coincidir las propiedades por nombre.
No estás asignando el elenco a nada.
var myClass = new Child();
Parent p = (Parent)myClass;
Editar - Creo que no entiendes cómo funciona el casting. Supongamos que Parent tiene un método virtual
, DoStuff()
que se invalida en Child
. Incluso si myClass
a Parent
, se ejecutará el método DoStuff
del Child
. No importa qué, ese Child
es un Child
, y siempre será un Child
, incluso si lo lanzas.
Si está intentando pasarlo a un método que acepta un objeto principal, no tiene que lanzarlo. Ya es un Parent
, en virtud de ser un Child
.
Creo que nos estamos perdiendo algo. ¿Qué estás tratando de lograr? ¿Qué no funciona?
Si Parent
es una superclase de Child
, entonces automáticamente un Child
es también Parent
(contiene todas las propiedades y métodos de `Parent) y no es necesario realizar la conversión.
Además, no puedes simplemente comenzar una línea con un lanzamiento. Podrías escribir por ejemplo
Parent p = (Parent)myClass;
Tuve el mismo problema y se me ocurrió la siguiente solución:
Mi código inicial fue así:
public class Person
{
public string Name { get; set; }
public Person() {};
public Person( Person rhs )
{
Name = rhs.Name;
}
}
public class Customer : Person
{
private string m_role = "Customer";
public string Role { get m_role; }
public Customer() : base();
}
public class Employee : Person
{
private string m_role = "Employee";
public string Role { get m_role; }
public Employee() : base();
}
y cuando intenté lanzar un objeto Person a un cliente, recibí errores de "error de lanzamiento"
En lugar de seguir con la idea de lanzar, decidí modificar los constructores de copias del Niño, por lo tanto:
public class Customer : Person
{
private string m_role = "Customer";
public string Role { get m_role; }
public Customer() : base();
public Customer( Person per ) : base( per);
}
public class Employee : Person
{
private string m_role = "Employee";
public string Role { get m_role; }
public Employee () : base();
public Employee ( Person per) : base( per);
}
podría usar el operador como ... lo bueno de ESO es que no se lanzará ninguna excepción y puede verificar si el "lanzamiento" falla.
public class Parent
{
public string name{get;set;}
}
public class child : Parent{}
var myClass = new Child()
Parent foo = myClass as Parent
if ( foo == null ) Debug.WriteLine("foo is NOT of type Parent");