2010-02-28 14 views
7

Dado el siguiente código de cliente:¿Puede un constructor devolver una subclase?

var obj = new Class1(); 

¿Hay alguna manera de modificar el constructor de Class1 por lo que en realidad se volverá una subclase (o alguna otra implementación alternativa) en su lugar?

Me gustaría obj obtener una de dos implementaciones diferentes, dependiendo de alguna condición. Obviamente, podría cambiar a usar un marco DI o de fábrica, pero me gustaría evitar cambiar el código del cliente, si es posible.

Supongo que la respuesta es no, pero me pregunto si hay alguna manera inteligente de lograrlo.

+4

Estamos considerando agregar una característica "extensión nueva" que básicamente le permitiría hacer un método de fábrica estático que se llamaría cuando se utiliza el "nuevo" operador, de forma similar a los métodos de extensión cuando se llama al ". operador es usado Sería un buen azúcar sintáctico para la fábrica. Si tienes un escenario realmente increíble donde este tipo de patrón sería útil, me gustaría ver un ejemplo. –

+1

@Eric: si bien no es un ejemplo de C# específicamente, me he encontrado con una situación en la que esto sería útil en C++. Estoy desarrollando una biblioteca multiplataforma, y ​​sería realmente útil para un ABC independiente de la plataforma poder devolver una instancia de clase derivada específica de la plataforma de su constructor. Estoy seguro de que debe haber situaciones similares cuando se desarrolla con C#. – Mac

+0

@Eric Lippert - ¡Tengo un escenario del mundo real para ti! http://blog.hackensplat.com/2010/09/construct-something-else-c.html – billpg

Respuesta

4

Esto no es posible.

Las soluciones provisionales incluyen reemplazar el constructor con una función static o (no recomendado) usando un contenedor alrededor de la clase base y crear diferentes clases envueltas.

8

Puede reemplazar el constructor con un método de fábrica, y devolver lo que quiera, en función de los parámetros:

public Class2 : Class1 {} 

public static Class1 CreateClass1(bool returnDerivedClass) 
{ 
    if (returnDerivedClass) 
    { 
     return new Class2(); 
    } 
    else 
    { 
     return new Class1(); 
    } 
} 
0

Por cosas como estas desea comprobar el patrón de fábrica. Además, según sus necesidades, le recomiendo consultar los métodos generales para reducir el acoplamiento. Su llamada al constructor de la clase es el acoplamiento más difícil que puede tener en un programa y hace cosas como intercambiar la implementación, como descubrió usted mismo.

Lea acerca de "Inversión de control" y "Inyección de dependencia", tal vez eso es lo que realmente busca.

Una buena biblioteca se puede encontrar here.

0

Utilice una biblioteca de inyección. El siguiente enlace presenta una gran lista de bibliotecas de inyección por ahí y comparación de su desempeño

http://www.palmmedia.de/blog/2011/8/30/ioc-container-benchmark-performance-comparison

Yo sugeriría sin embargo, que el rendimiento no suele ser un criterio que se elija una biblioteca de inyección en la mayoría de las aplicaciones no instanciar la cantidad de objetos que este tipo ha usado en sus pruebas. Estoy usando NInject, que hace bien el trabajo, sin embargo, si tuviera que comenzar otro proyecto probablemente daría una oportunidad a simpleinjector, parece que tiene todas las características que uso en NInject y funciona bien en las comparaciones de rendimiento.

Cuestiones relacionadas