¿Cómo hacer que un objeto idisible sea una variable de clase?
-
19-09-2019 - |
Pregunta
Estoy trabajando con Active Directory usando C#. Instanciando el PrincipalContext
El objeto parece ser costoso, por lo que me gustaría almacenar uno en una variable de clase.
Cuando usas PrincipalContext
Como variable local, puedo usar el conveniente using
sintaxis. Al almacenar un IDisposable
Objeto en una variable estática, ¿cómo me aseguro de que el objeto se elimine correctamente?
Solución
El patrón general para esto es implementar el IDisposable
interfaz en su clase. Tome este ejemplo:
public class YourClass : IDisposable
{
private OtherDisposableType yourResource;
public YourClass()
{
yourResource = new OtherDisposableType();
}
public void Dispose()
{
yourResource.Dispose();
}
}
Esto es, como mínimo, lo que necesita hacer.
EDITAR
Mi versión anterior abogó por seguir el patrón finalizador en todos los casos, que (correctamente) señaló que estaba en contra de las pautas de diseño del marco. Sin embargo, en el caso de que realmente esté tratando con recursos no administrados (por ejemplo, está haciendo llamadas directas de P/Invoke y obteniendo un mango que debe liberarse explícitamente) es aconsejable que cree un finalizador y una llamada Dispose
Dentro de él para proteger contra las personas que consumen su código y no llaman Dispose
:
public class YourClass : IDisposable
{
private OtherDisposableType yourResource;
public YourClass()
{
yourResource = new OtherDisposableType();
}
public void Dispose()
{
yourResource.Dispose();
GC.SuppressFinalize(this);
}
~YourClass()
{
Dispose();
}
}
Otros consejos
Mira lo que el System.ComponentModel
el espacio de nombres sí. Básicamente, el patrón que normalmente uso es tener una colección de subcomponentes, que incluye todo lo que tengo que no es un 'valor', ya sea que implementa o no IDisposable
.
Entonces, cuando yo Dispose()
yo mismo, itero sobre esta colección y Dispose
Cualquier cosa que implementa IDisposable
.
Una ventaja de esta técnica es que si un objeto que tengo comienza a ser desechable, pero luego agrega el IDisposable
Interfaz, mi clase hará lo correcto sin tener que cambiar.
Además, el uso de un contenedor DI/IOC puede manejar gran parte de esto para usted.
Básicamente, quieres almacenar en caché un recurso costoso. Eso es bueno.
Los datos globales (variables estáticas en este caso) no son tan buenos, en mi humilde opinión. En cambio, ¿por qué no convertirla en una variable de instancia y controlar la vida útil?
Escriba su clase que maneje las responsabilidades publicitarias, haga que cree y use el PrincipalContext, y haga que sea idisible también (usando el Desechar el patrón). Extraiga una interfaz de él para desacoplarlo y hacer clases que lo usen más fácilmente de probar.
Las clases que desean usar servicios publicitarios tomarán un parámetro de constructor de su nueva interfaz (Inyección de dependencia o di). Puede crear su clase manualmente en un bloque de uso y pasarla a las clases o usar un Marco de contenedores DI. Puede hacer que el marco establezca la vida útil del objeto AD a la vida útil del contenedor (que también puede ser idisable). Ver ¿Cómo se reconcilia Idisposable e IOC? y su documentación de contenedor DI para obtener más información sobre esto.