2009-06-17 13 views
8

Estoy trabajando con una clase C# de terceros que tiene muchos excelentes métodos y propiedades, pero a medida que pasa el tiempo necesito extender esa clase con métodos y propiedades propias. Si fuera mi código, simplemente usaría esa clase como mi clase base y agregaría mis propias propiedades y método en la parte superior, pero esta clase tiene un constructor interno. (En mi opinión, fue corto para hacer el constructor interno en primer lugar, ¿por qué limitar la capacidad de subclase?)¿Hay alguna manera de derivar de una clase con un constructor interno?

Lo único que se me ocurrió fue crear un método/propiedades en mi clase que simplemente llamara de ellos, pero son acres de código y, bueno, simplemente no "se siente" bien.

¿Hay alguna forma de utilizar esta clase como clase base?

+1

Primera parte: http://blogs.msdn.com/ericlippert/archive/2008/09/26/preventing-third-party-derivation-part-one.aspx –

+1

Segunda parte: http: //blogs.msdn .com/ericlippert/archive/2008/10/06/prevention-third-party-derivation-part-two.aspx –

Respuesta

0

No discutiré si puedes construir tu propia Fachada en torno a esa clase de terceros. Los autores anteriores tienen razón, la biblioteca podría diseñarse de la manera que no lo permita. Supongamos que tienen algunas clases acopladas que tienen singletons que se deben inicializar en un orden específico o algo así, puede haber muchos errores de diseño (o características) que a los desarrolladores de terceros nunca les importan, porque no suponen que va a utilizar su biblioteca de esa manera.

Pero bien, supongamos que construir una fachada no es una tarea imposible, y de hecho tiene un solo problema: , hay demasiados métodos para escribir envoltorios alrededor de, y no es bueno hacerlo a mano.

veo 3 soluciones para hacer frente a ese problema exactamente

1) supongo que los nuevos tipos "dinámicas" de .NET 4.0 le permitirán Para solucionar ese problema sin tener que escribir "acres de código" Usted debe Incapsule una instancia de una clase de terceros en su clase como un miembro privado con la palabra clave dinámica . Su clase debe derivarse de Dynamic o implementar la interfaz IDynamicObject. Usted tendrá que implementar funciones/SetMember GetMember que reenviará todas las llamadas a la instancia encapsulada de clase tercera parte

Bueno, C# 4.0 es un futuro, Vamos a ver en otras soluciones:

2) No escribir código manualmente si tiene una cantidad significativa de métodos públicos (por ejemplo, más de 100). Escribía una pequeña aplicación de consola que usa la reflexión y encuentra todos los miembros públicos y luego genera código automáticamente para llamar a la instancia encapsulada. Por ejemplo

public type MethodName(params) 
{ 
    this.anInstanceOf3rdPartyClass.MethodName(params); 
} 

3) Se puede hacer lo mismo que 2, pero con la ayuda de herramientas de reflexión existentes, por ejemplo Redgate .NET Reflector. Le ayudará a enumerar todas las clases y firmas de métodos. A continuación, pegue todo esto en Word y una macro simple de VB le permitirá generar el mismo código que podría hacer en 2. Observación: Tan pronto como no copie el código, solo copie las firmas de métodos, que estén disponibles al público , No creo que viole el acuerdo de licencia, pero de todos modos vale la pena volver a verificar

2

Solo si su clase vive en el mismo ensamblaje que la clase de la que desea heredar. Un constructor interno limita las implementaciones concretas de la clase abstracta al ensamblaje que define la clase. Una clase que contiene un constructor interno no se puede instanciar fuera del ensamblado.

2

suena como una aplicación perfecta para los métodos de extensión:

MSDN extension method docs

"Los métodos de extensión le permiten 'añadir' métodos a los tipos existentes sin crear un nuevo tipo derivado, recompilar, o de otra manera modificar el tipo original Los métodos de extensión son un tipo especial de método estático, pero se llaman como si fueran métodos de instancia en el tipo extendido. Para el código de cliente escrito en C# y Visual Basic, no hay diferencia aparente entre llamar a un método de extensión y los métodos que en realidad están definidos en un tipo ".

+0

Acabas de "actualizarlo" de la misma manera que ya lo haces - mágicamente obtiene nuevos métodos que tienes agregado a esto – Bruce

+0

Los métodos de extensión solo son buenos en lugares donde se pueden usar métodos estáticos. Además, también se debe incluir el espacio de nombres que contiene la clase con los métodos de extensión. Por ejemplo, no podría tener propiedades que almacenen estado. –

+0

Entendido sobre el estado: existen limitaciones. No entiendo su comentario acerca de los métodos estáticos; claro, el método de extensión es estático, pero tiene acceso a la instancia del objeto a través del parámetro 'this'. – Bruce

2

Si la clase tiene un constructor interno y no hay constructores públicos, eso sugiere que los diseñadores no intentaron que se subclasificara. En ese caso, puede usar la encapsulación, o puede usar métodos de extensión.

5

Pregunta: "¿Por qué limitar la capacidad de subclase?"

Porque diseñar para la herencia es complicado, especialmente si está diseñando para que otros desarrolladores hereden de su clase. Como dice Josh Bloch en Java efectivo, debes diseñar para heredar o prohibirlo. En mi opinión, a menos que tenga una buena razón para diseñar la herencia, no debería hacerlo de forma especulativa.

¿La clase implementa una interfaz que también puede implementar (posiblemente enviando la mayoría de las llamadas a una instancia del original)? A menudo no hay una respuesta realmente elegante aquí, y la mejor solución dependerá de la situación exacta, incluido lo que estás tratando de agregar a la clase.

Si no agrega más métodos de conveniencia, simplemente convenientes, los métodos de extensión pueden funcionar bien para usted. Pero no cambian los datos que un objeto es capaz de almacenar, por lo que si necesita agregar sus propios datos especializados, eso no funcionará.

1

Resharper tiene una buena característica para crear miembros que deleguen.

Here es una muestra de lo que puede hacer con él. Toma un par de segundos.

Cuestiones relacionadas