Pregunta

Tengo el siguiente código de ejemplo:

public interface IRepository {
   // Whatever
}

public class SampleRepository : IRepository {
   // Implements 'Whatever'
}

public class NHibernateRepository : IRepository, IDisposable {

   // ...

   public void Dispose() { ... }
}

Ahora - es que muy mal No estoy seguro, pero esto parece ser bastante lo mismo que no marcar el destructor de la clase base virtual en C++ ? .

Yo no quiero hacer que la interfaz IRepository implementar IDisposable, porque eso haría que la complejidad no deseada y el manojo de clases que también tendría que aplicar IDisposable.


¿Cómo debe ser manejado este caso?

Estoy seguro de que esto pueda suceder a cualquier tipo de jerarquía -. Cuando uno de tipo derivado tiene que gestionar los recursos disponibles

Entonces, ¿qué debo hacer? - tire de la IDisposable hasta la primera interfaz o dejarlo como usuario y esperanza distinguiría depósitos desechables y no desechables

Gracias.

¿Fue útil?

Solución

Lo que usted ha descrito está bien con una salvedad importante: un objeto de un tipo que ha añadido 'IDisposable' a su base no se debe pasar a un consumidor que puede terminar la tenencia o la persistencia del objeto para una duración desconocida.

Básicamente, el propietario de un objeto imprescindible IDisposable (*) o bien cuidar de disponer el objeto en sí mismo, o entregar el objeto fuera a un nuevo propietario que puede aceptar y cumplir con la responsabilidad. Inicialmente, los objetos IDisposable generalmente son "propiedad" de su creador, pero traspasos son comunes. Una referencia a un objeto IDispoable se puede dar a otro objeto sin transferir la propiedad; En ese escenario, el propietario sigue siendo responsable de la eliminación del objeto cuando ya no se necesita. Para que esto suceda, el propietario tiene que conocer el objeto ya no es necesaria. Los patrones más comunes son:

  1. El objeto se pasa como un parámetro a un método; el objeto que aloja el método no utilizará el objeto después se devuelve el método.
  2. El objeto se pasa como un parámetro a un método que almacenarlo en el campo de algún objeto, pero que más tarde objeto de alguna manera se puede solicitar para destruir la referencia.
  3. El desechable se pasa como un parámetro a un método que se aloja por un objeto al cual el propietario del objeto desechable sostiene todas las referencias; el objeto de alojamiento no utilizará el objeto desechable a menos que se solicite, y el propietario del objeto desechable sabrá si nunca emitió ningún varias de dichas solicitudes.

Si se aplica uno de esos patrones, que puede estar en buena forma. Si no se puede estar en problemas.

Otros consejos

Sí, yo diría que esto es malo -. Porque no se puede utilizar todos los repositorios de la misma manera

Yo personalmente haría que la interfaz de repositorio de extender IDisposable -. Que es bastante fácil de implementar con un no-op, después de todo

Esta es exactamente la misma elección que se hace por Stream, TextReader y TextWriter en el marco principal. StringWriter (por ejemplo) no necesita disponer de nada ... pero sigue siendo TextWriter desechable.

Todo esto viene a cuento porque IDisposable es en cierto modo una interfaz extraña: no transmite algo que es ofrecido a las personas que llaman ... Transmite algo que es requerida de las personas que llaman (o, al menos, alentado fuertemente con los posibles problemas si no van junto con ella).

El único problema que puede tener es si está utilizando algún tipo de fábrica, Inversión de Control, o la dependencia patrón de inyección / marco. Si alguna vez desea utilizar el objeto como una interfaz, usted nunca será capaz de hacer esto:

IRepository repo = Factory.GetRepository();
repo.Dispose();

Es posible que desee introducir un INHibernateRepository que implementa IDisposable. Debido IDisposable es generalmente una operación de nivel tan bajo, no hay un gran problema con la fabricación de sus interfaces de la aplicación de esta interfaz.

No, no "tirar de la IDisposable arriba". Mantenga las interfaces atómica, sencilla e independiente.

A menos que se podría argumentar que el ser IDisposable es un rasgo fundamental de IRepository (y espectáculos SampleRepository no lo es) que no debería haber ninguna derivación entre los dos.

Esto parece perfectamente bien para mí. ¿Cuál es el problema?

En primer lugar, para responder a su pregunta. El patrón dispose es diferente de un destructor C ++. Un método Dispose está destinado a disponer de recursos contenido por la clase , en lugar de disponer de la clase en sí .

La razón para el marcado de los destructores C ++ como virtual no existir en .NET porque cada instancia de un tipo de referencia tiene un bloque de sincronización que contiene información del tipo de tiempo de ejecución. Usando esto, el colector de basura puede recuperar adecuadamente la cantidad correcta de memoria.

Como para extender IRepository con IDisposable, que sería una solución rápida que sería aceptable en la gran mayoría de los casos. La única objeción que puedo ver es que la ampliación de la interfaz requerirá que todas las clases derivadas para implementar la interfaz. A primera vista, puede parecer fácil de implementar una interfaz con NOP (quizás varias veces), pero no tiene por qué. Pero, puedo ofrecer una alternativa.

En su lugar, considere el uso de una clase base abstracta que implementa el patrón Dispose. Esto seguiría la estructura de la aplicación "estándar" del patrón de disponer.

public abstract class Repository : IDisposable  
{ 
    public void Dispose() { Dispose(true); }
    protected virtual Dispose(bool disposing) {  } 
}

public class NHibernateRepository : Repository { /* Impl here, add disposal. */ }

public class TestRepository : Repository { /* Impl with no resources */ }

Tome un vistazo a la Desechar Directrices patrón escrito por Microsoft para ver un ejemplo más detallado.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top