2010-03-25 16 views
7

Extiendo la clase existente de .NET framework derivandolo. ¿Cómo convierto un objeto de tipo base a tipo derivado?Convertir/Fundir tipo de base en el tipo Derivado

public class Results { //Framework methods } 

public class MyResults : Results { //Nothing here } 

//I call the framework method 

public static MyResults GetResults() 
{ 
    Results results = new Results(); 
    //Results results = new MyResults(); //tried this as well. 

    results = CallFrameworkMethod(); 

    return (MyResults)results; //Throws runtime exception 
} 

entiendo que esto ocurre como estoy tratando de echar un tipo base de un tipo derivado y si el tipo de derivado tiene propiedades adicionales, entonces la memoria no se ha asignado. Cuando agregue las propiedades adicionales, no me importa si se inicializan como nulas.

¿Cómo hago esto sin hacer una copia manual?

+1

En lugar de extender el tipo, ¿puede simplemente crear un método de extensión? –

+0

Esta es una buena idea. Con los métodos de extensión, puedo adjuntar nuevos métodos. Realmente no puedo agregar propiedades/variables adicionales al tipo. – Nick

+0

Parece mucho trabajo evitar escribir un simple constructor de copia. Sé que en muchos casos eso no es posible, pero parece una posible solución en este caso. – overslacked

Respuesta

11

No se puede . Si results no se refiere a MyResults (por ejemplo, si CallFrameworkMethod devuelve una instancia de base Results), entonces la conversión no lo hará así: tendrá que crear un nuevo MyResults, basado en el no existente MyResults. Casting se trata de cambiar el tipo de tiempo de compilación de la referencia , no de cambiar el tipo concreto del objeto al que se hace referencia.

se pueden utilizar herramientas tales como la reflexión o AutoMapper para ayudar con la inicialización del nuevo objeto MyResults - pero un nuevo MyResults objeto no debe ser, porque no se puede contar una base de Results objeto para convertirse en un objeto MyResults.

+0

¿Esto tiene que ver con la varianza/covarianza? Estoy en .NET 4.0 y sé que hicieron algo por varianza/covarianza. ¿Alguna idea? – Nick

+0

No, la variación de C# 4.0 tiene que ver con cuando se usan tipos base/derivados como parámetros de tipo para interfaces genéricas o delegados; y no tiene ninguna interfaz genérica o delegados aquí. Tu problema es más fundamental: se trata del tipo concreto del objeto. Un objeto Results simplemente * no es * una instancia del tipo MyResults. Si CallFrameworkMethod devuelve resultados (reales), las referencias a ese objeto * no pueden * ser enviadas a MyResults porque el objeto * no es * a MyResults. La única forma de evitar esto es cambiar CallFrameworkMethod para devolver MyResults o crear un MyResults nuevo. – itowlson

+0

varianza no lo ayudará aquí –

1

¿Qué tal:

... 
MyResults results = new MyResults(); 
... 

Y tal vez también es necesario para crear un constructor en la clase MyResults:

public class MyResults : Results 
{ 
    public MyResults() : base() {} 
} 

¿Qué significa exactamente "nada aquí"?

EDITAR

results = (CallFrameworkMethod() as MyResults); 

Eso no emitir la excepción, pero si sería útil para usted - que depende de lo que le gustaría hacer más ...

+0

"nada aquí" como en literalmente nada. Por ahora, he heredado del tipo base con la intención de agregar nuevas propiedades en el futuro – Nick

+0

que veo. Edité mi respuesta: compruebe la nueva solución. – Gacek

+0

@Gacek: el uso de la palabra clave as no arroja una excepción, pero el objeto MyResult es nulo, aunque CallFrameworkMethod devuelve un objeto no nulo. – Nick

0
Results results = new MyResults(); 
    ... 

return (MyResults)results; 

debería funcionar. Si no, entonces el problema está en otro lugar.

+1

No, porque luego lo sobreescribe con el valor de retorno de CallFrameworkMethod, que presuntamente devuelve algo que no sea MyResults, o el lanzamiento tendrá éxito. – itowlson

+0

CallFrameworkMethod() devuelve el objeto de tipo Resultados – Nick

+0

Hace una instancia de la clase MyResult y luego llama al método CallFrameworkMethod que asigna al objeto de resultados alguna otra instancia que no se puede convertir. – Machta

1

No, no puede evitar copiar el contenido en una instancia del tipo derivado. Bien, si puede cambiar el método CallFrameworkMethod para que sea un método genérico, y MyResults tiene un constructor de argumento cero, CallFrameworkMethod podría crear una nueva instancia de su tipo derivado directamente y luego usar solo los miembros del tipo padre.

Pero probablemente tendrá que terminar copiando a un nuevo objeto. Recuerde que este código de copia puede ser reutilizado en otro método, no es necesario que lo reescriba donde lo necesite.

+0

¿Cómo se vería el constructor de copias? ¿Me puede dar algunos consejos? – Nick

+0

C# no tiene "constructores de copia". Pero ciertamente puede escribir un método reutilizable que acepte la clase base y devuelva una instancia de la clase derivada, con todos los miembros de la clase base copiados. ¿O estabas preguntando sobre la idea genérica? –

1

Como han dicho las respuestas anteriores, debe instanciar una nueva instancia de MyResults y luego copiar las propiedades desde su objeto Results. Usted preguntó qué era un "constructor de copia": es simplemente un constructor que toma un objeto y lo utiliza para poblar el objeto que se está construyendo.Por ejemplo:

public class Results 
    { 
     public string SampleProperty1 { get; set; } 
     public string SampleProperty2 { get; set; } 
    } 

    public class MyResults : Results 
    { 
     public MyResults(Results results) 
     { 
      SampleProperty1 = results.SampleProperty1; 
      SampleProperty2 = results.SampleProperty2; 
     } 
    } 

Un constructor de copia es por lo general más conveniente, fácil de leer y reutilizable que usar un código como éste:

MyResults myResults = new MyResults 
{ 
    SampleProperty1 = results.SampleProperty1, 
    SampleProperty2 = results.SampleProperty2 
}; 

Si hay un montón de propiedades y/o que están haciendo muchos cambios a la clase puede usar la reflexión (por ejemplo, C# Using Reflection to copy base class properties) o una herramienta como AutoMapper (http://automapper.codeplex.com) para copiar las propiedades. Pero a menudo eso puede ser excesivo.

Cuestiones relacionadas