otro - ¿Cuál es la mejor manera de implementar una constante global en C#?
funcion global c# (7)
Como dije antes, no es el mismo escenario:
- const: es contant y no se puede modificar excepto mediante recompilación.
- readonly: el valor se inicializa en la declaración o en el constructor y permanece solo después.
Cuando una declaración de campo incluye un modificador de solo lectura, las asignaciones a los campos introducidos por la declaración solo pueden ocurrir como parte de la declaración o en un constructor en la misma clase
Tengo un proyecto común dentro del cual he agregado mis constantes públicas para QueryStringNames.
Sé que, en general, las constantes deben ser internas o privadas, pero necesitaría constantes públicas aquí, ya que me gustaría permitir un acceso global a los nombres de cadena de consulta, claves de sesión, etc.
Hay 3 soluciones que conozco pero todas tienen un problema importante. El conjunto llamante contendría la copia de mi constante, lo que significa que si tuviera que cambiar un valor constante, ¡tendré que compilar tanto mi ensamblaje común como el ensamblador de llamante!
1) public const string ConstName = "a value";
2) public readonly string ConstName = "a value";
3) To be stored in a public resource file.
¿Cuál sería el mejor enfoque para definir constantes públicas en C # además de almacenarlas en el archivo web.config (que no tiene intellisense)?
Depende. Si realmente es una constante que no cambiará, incluso en futuras versiones de tu código, entonces const
está bien. De lo contrario, vaya con un campo de static readonly
.
Un const
se integrará en el conjunto de llamada, mientras que con static readonly
el conjunto de llamada solo contiene una referencia al campo. Esto significa que const
requiere la recopilación de todo el código dependiente cada vez que cambie el valor, mientras que el public readonly
utiliza el nuevo valor, incluso sin volver a compilar el ensamblado que realiza la llamada.
Si desea almacenar la "constante" en un archivo de configuración, pero como Intellisense, puede usar una propiedad sin setter público. Y luego llenarlo desde el archivo de configuración en tiempo de ejecución. Pero yo diría que los valores de configuración no deberían ser static
en primer lugar. Para los valores de configuración usaría un singleton de algún tipo, preferiblemente la variación IoC y no la Class.Instance
. Variación de la información. Entonces definiría una interfaz como la siguiente:
interface IMyConfig
{
string Key{get;}
}
Y tienen clases que necesitan esta configuración, tómenlo como un parámetro constructor:
public MyClass(IMyConfig config)
{
...
}
Prefiero la segunda opción en la mayoría de los casos, ya que no causará problemas (al copiar el valor en otros ensambles). La velocidad puede ser más lenta que las constantes, pero este tipo de velocidad nano-segundo es bastante inmadura.
Puede usar el objeto Cache y definirlos en Global.asax
Si crees que lo cambiarías y te preocupa tener que compilarlo, ¿por qué no utilizar appSettings en el archivo de configuración web? Para eso es para eso. Si realmente necesita intellisense, puede colocar una clase en uno de los ensamblados que lea el valor de configuración y lo exponga como una propiedad para facilitar la referencia. Si se trata de datos confidenciales, entonces no los incluiría en un archivo de configuración, solo lo compilaría de todos modos, ya que no quiere comprometer su aplicación.
<appSettings>
<add key="myconstant" value="here''s the value!" />
</appSettings>
Aquí está la clase para hacer referencia a ese valor, lo que le da intellisense, capacidad para cambiarlo fácilmente en el futuro, y sin tener que recompilar nada
public class MyAppConfigSettings
{
public string MyConstant { get; private set; }
public MyAppConfigSettings()
{
MyConstant = ConfigurationManager.AppSettings["myconst"];
}
}
Puede que no sea la respuesta a su solución, pero puede brindarle otras ideas.
Si está activando fxCop (herramienta de análisis de código incluida en la distribución de Visual Studio), puede hacer que la sugestión cambie constante para convertirse en:
cadena de solo lectura pública estática ConstName = "a value";
No estoy seguro si entiendo el problema completamente ... ¿está pidiendo una solución para almacenar algunas variables globales que no causarán recompilaciones a ensamblajes que hacen referencia a esas variables globales si las cambia? Si es así, ¿por qué no intentas rediseñar tu arquitectura de acuerdo con el principio de inversión de control ? Piensa "no nos llames, te llamaremos" el principio de hollywood. Si todos los ensamblados que requieren alguna interfaz solo llaman a una interfaz (que poseen) que expone una propiedad con el valor que requieren, y luego tiene un proyecto de constantes que implementan esa interfaz (haciendo referencia a esos proyectos y luego implementando esas interfaces) entonces esos proyectos nunca necesitarán volver a compilarse cuando cambie el valor de las constantes.
Estoy seguro de que los conoce de todos modos, pero lea los principios SOLIDOS , "D" es el principio de Inversión de Dependencia (Inversión del Control). Creo que dadas tus preocupaciones (suponiendo que te haya entendido bien) podrían ayudarte.
Un ejemplo de Inversión de control podría ser tan simple como:
MyService.dll:
public class MyService
{
// injected dependency
public IMyConstants MyConstants { get; set; }
public MyMethod(){
// get your query...
var query = IMyConstants.Query;
}
}
MyConstants.dll:
public MyConstants : IMyConstants {
// implementation of query property from the myservices.dll interface
public string Query { ... }
}
Por lo tanto, myconstants.dll hace referencia a myservice.dll en lugar de al revés (lo que significa que myservices no necesitará recompilar). Entonces el código de arranque (para configurarlo todo e inyectar dependencias) vive en otro lugar.
Lo siento si te entendí mal, ¡espero que ayude!