Nuestro software tiene varias clases que se deben encontrar dinámicamente a través de la reflexión. Todas las clases tienen un constructor con una firma específica a través de la cual el código de reflexión crea instancias de objetos.
Sin embargo, cuando alguien comprueba si se hace referencia al método (por ejemplo, a través de la lente de código de Visual Studio), la referencia a través de la reflexión no se cuenta. Las personas pueden perder sus referencias y eliminar (o cambiar) métodos aparentemente no utilizados.
¿Cómo debemos marcar / documentar los métodos destinados a ser llamados a través de la reflexión?
Idealmente, el método debe marcarse de tal manera que tanto los colegas como Visual Studio / Roslyn y otras herramientas automatizadas "vean" que el método debe llamarse mediante reflexión.
Sé de dos opciones que podemos usar, pero ambas no son del todo satisfactorias. Como Visual Studio no puede encontrar las referencias:
- Use un atributo personalizado y marque el constructor con este atributo.
- Un problema es que las propiedades de atributo no pueden ser una referencia de método, por lo tanto, el constructor seguirá mostrando que tiene 0 referencias.
- Los colegas que no estén familiarizados con el atributo personalizado probablemente lo ignorarán.
- Una ventaja de mi enfoque actual es que la parte de reflexión puede usar el atributo para encontrar el constructor al que debería llamar.
- Utilice los comentarios para documentar que un método / constructor está destinado a llamarse mediante reflexión.
- Las herramientas automatizadas ignoran los comentarios (y los colegas también podrían hacerlo).
- Los Comentarios de documentación Xml se pueden usar para que Visual Studio cuente una referencia adicional al método / constructor:
SeaMyPlugin
la clase cuyo constructor invocar mediante reflexión. Suponga que el código de reflexión de invocación busca constructores que toman unint
parámetro. La siguiente documentación muestra que la lente de código muestra que el constructor tiene 1 referencia:
/// <see cref="MyPlugin.MyPlugin(int)"/> is invoked via reflection
¿Qué mejores opciones existen?
¿Cuál es la mejor práctica para marcar un método / constructor que se pretende llamar mediante reflexión?
fuente
Respuestas:
Una combinación de las soluciones sugeridas:
Esto debería aclarar el uso previsto para los colegas (y mi futuro yo).
<see>
etiqueta para aumentar el recuento de referencias para el constructor / método.Esto hace que la lente de código y las referencias de búsqueda muestren que se hace referencia al constructor / método.
UsedImplicitlyAttribute
[UsedImplicitly]
tiene precisamente la semántica prevista.PM>
Install-Package JetBrains.Annotations
.SupressMessageAttribute
para el mensajeCA1811: Avoid uncalled private code
.Por ejemplo:
La solución confiere el uso previsto del constructor tanto a los lectores humanos como a los 3 sistemas de análisis de código estático más utilizados con C # y Visual Studio.
La desventaja es que tanto un comentario como una o dos anotaciones pueden parecer un poco redundantes.
fuente
MeansImplicitUseAttribute
se puede usar para crear sus propios atributos que tengan unUsedImplicitly
efecto. Esto puede reducir mucho ruido de atributos en las situaciones correctas.Nunca he tenido este problema en un proyecto .Net, pero regularmente tengo el mismo problema con los proyectos Java. Mi enfoque habitual allí es usar la
@SuppressWarnings("unused")
anotación agregando un comentario que explique por qué (documentar la razón por la que se desactivan las advertencias es parte de mi estilo de código estándar; cada vez que el compilador no puede resolver algo, supongo que es probable que un humano tenga dificultades también). Esto tiene la ventaja de garantizar automáticamente que las herramientas de análisis estático sean conscientes de que no se supone que el código tenga referencias directas, y de dar una razón detallada para los lectores humanos.El equivalente de C # de Java
@SuppressWarnings
esSuppressMessageAttribute
. Para métodos privados , puede usar el mensaje CA1811: Evite el código privado no llamado ; p.ej:fuente
SuppressMessageAttribute
( msdn.microsoft.com/en-us/library/… ). El mensaje que más se acerca esCA1811: Avoid uncalled private code
( msdn.microsoft.com/en-us/library/ms182264.aspx ); Todavía no he encontrado un mensaje para el código público.Una alternativa a la documentación sería realizar pruebas unitarias para asegurarse de que las llamadas de reflexión se ejecuten correctamente.
De esa manera, si alguien cambia o elimina los métodos, su proceso de compilación / prueba debería alertarlo de que ha roto algo.
fuente
Bueno, sin ver su código, parece que este sería un buen lugar para introducir alguna herencia. ¿Quizás un método virtual o abstracto que el constructor de estas clases pueda llamar? Si eres el método que estás tratando de marcar es solo el constructor, entonces realmente estás tratando de marcar una clase y no un método, ¿sí? Algo que he hecho en el pasado para marcar clases es hacer una interfaz vacía. Luego, las herramientas de inspección de código y la refactorización pueden buscar clases que implementen la interfaz.
fuente