c# - valores - Settings.Default.<Property> siempre devuelve el valor predeterminado en lugar del valor en el almacenamiento persistente(archivo XML)
tipos de datos en c# visual studio (9)
He visto un problema similar cuando uso app.config. Intente ejecutar su aplicación desde .exe en lugar de desde Visual Studio y vea si luego se comporta como se esperaba.
Recientemente escribí una DLL en C # (.Net 2.0) que contiene una clase que requiere una dirección IP. Un compañero de trabajo mío alteró la clase para recuperar el IP de un archivo ".dll.config" (XML). Esto aparentemente se genera automáticamente por el archivo "Configuraciones de la aplicación" que creó (Settings1.settings). El beneficio de esto fue permitir que el usuario final cambie la dirección IP en el archivo XML / config a voluntad.
Desafortunadamente, cuando reviso su código fuera del árbol y trato de compilar (o usar) este nuevo código, cualquier aplicación que llame a este DLL solo obtiene el valor predeterminado, en lugar del valor del archivo.
El constructor que llama al archivo de configuración se ve así:
public class form : System.Windows.Forms.Form
{
public form()
{
// This call is required by the Windows Form Designer.
InitializeComponent();
IP = IPAddress.Parse(Settings1.Default.IPAddress);
}
}
Encontré una referencia a este problema en los foros de MSDN donde un usuario dijo:
los valores ''antiguos'' (los que define en el momento del desarrollo) están codificados. Si el franework no puede acceder o abrir el archivo de configuración, usará los valores predeterminados en su lugar. Esto siempre ocurrirá si usa la configuración en un dll.
¿Esto significa que no puedo almacenar un valor externo para una DLL en un archivo de configuración? (Mi compañero de trabajo de alguna manera hizo que esto funcione ...)
Dado que mi marco parece no poder acceder o abrir el archivo de configuración, ¿cómo puedo descubrir por qué está fallando? ¿O incluso detectar cuando sucede esto?
Decker : Eso ayuda un poco. Lamentablemente, estoy escribiendo esta DLL en una especificación, por lo que no tengo acceso al archivo de configuración de la Aplicación. Como verá más arriba, mi compañero de trabajo creó un archivo "Configuración 1 .settings". No entendí esto en ese momento, pero ahora parece que agregar el "1" lo mantiene fuera del espacio de configuración de cualquier aplicación que lo llame.
Supongo que lo que intento averiguar es por qué el archivo DLL no parece encontrar el archivo de configuración al lado en el mismo directorio. El seguimiento paso a paso del código no revela nada.
Como comentario adicional, puedo cambiar el "Tipo de salida" de mi ensamblaje de "Biblioteca de clases" a "Aplicación de Windows" y agregar las siguientes líneas al comienzo de mi código DLL:
[STAThread]
public static void Main(string[] args)
{
System.Windows.Forms.Application.Run(new form());
}
Cuando ejecuto esto, genera un archivo de configuración diferente (un ".exe.config") y puedo modificarlo y hacer que extraiga los datos nuevos del archivo. Entonces estoy un poco confundido. ¿Algunas ideas?
Aparentemente su aplicación está tratando de leer desde el archivo de configuración predeterminado (que es probablemente el archivo de configuración de la aplicación). Para asegurarse, agregue el par clave-valor en el archivo de configuración del dll al archivo de configuración de la aplicación, ejecute la aplicación y vea si se lee esta vez.
Me estoy ocupando de este problema en una aplicación que estoy en medio de la creación de prototipos. Aunque la sugerencia de Decker de piratear los archivos de configuración juntos debería funcionar, creo que es un truco manual bastante inconveniente para realizar como parte de un ciclo de compilación. En lugar de eso, he decidido que la solución más limpia es hacer que cada biblioteca analice su propio archivo library.dll.config. Todavía no es perfecto y requiere un código extra de placa de caldera, pero parece ser la única forma de evitar la forma bizantina con la que .Net maneja estos archivos app.config.
Uso esta técnica todo el tiempo. A menudo tengo un ensamblaje de biblioteca que requiere ciertas configuraciones, y las necesito tanto probando proyectos como los ensamblajes "ejecutables" principales, ya sean proyectos web o proyectos de servicio de Windows.
Tiene razón en que cuando crea un archivo de configuración para cualquier proyecto, agrega un archivo de configuración de la aplicación. El valor que ingresa para cualquier configuración se almacena en dos lugares: el archivo de configuración Y en los atributos de las clases creadas por la infraestructura de configuración. Cuando no se encuentra un archivo de configuración, se utilizan los valores incrustados en los atributos.
Aquí hay un fragmento que muestra dicho atributo:
Aquí hay un fragmento que muestra el valor predeterminado de ConcordanceServicesEndpointName en la clase generada:
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("InternalTCP")]
public string ConcordanceServicesEndpointName {
get {
return ((string)(this["ConcordanceServicesEndpointName"]));
}
}
Lo que quiere hacer es copiar la sección de configuración fuera del archivo app.config del proyecto de ensamblaje de biblioteca y combinarlo (cuidadosamente) en el web.config o app.config aplicable para el ensamblaje principal. En tiempo de ejecución, ese es el único archivo de configuración que se utiliza.
Aquí hay un ejemplo:
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="LitigationPortal.Documents.BLL.DocumentsBLLSettings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<LitigationPortal.Documents.BLL.DocumentsBLLSettings>
<setting name="ConcordanceServicesEndpointName" serializeAs="String">
<value>InternalTCP</value>
</setting>
</KayeScholer.LitigationPortal.Documents.BLL.DocumentsBLLSettings>
</applicationSettings>
Debe copiar estas secciones en el archivo de configuración "verdadero".
He tenido el mismo problema durante mucho tiempo, es molesto.
Me gusta la idea de crear tu propio archivo de configuración y hacer que cada archivo DLL lo analice, aunque puede que sea fácil perder la necesidad de cambiar la configuración.
Una cosa que hice en el pasado para al menos facilitar esto es asegurarme de que cualquier valor de configuración que establezca el archivo Setting1.Settings sea inválido.
Por ejemplo, tengo una clase que usa LINQ-To-SQL para hablar con el DB. Por lo tanto, tiene un archivo Setting1.settings en el que almacena la cadena de conexión a la base de datos. El valor predeterminado que se ingresa (al arrastrar y soltar las tablas de la base de datos en el diseñador) es la cadena de conexión de la base de datos dev.
Una vez que tengo el archivo DBML creado a partir de la base de datos de prueba, puedo ingresar y editar el archivo de configuración y escribir un nombre de base de datos como "FAKE_DATABASE".
De esta forma, si usa el archivo DLL en otro proyecto y olvida combinar los archivos de configuración para agregar el valor de configuración adecuado para el archivo DLL, al menos obtendrá un mensaje de error que dirá algo así como "No se puede conectar con FAKE_DATABASE".
Por supuesto, si tiene que volver a trabajar con el diseñador, tendrá que volver a cambiar el valor al valor de su base de datos de desarrollo.
Gran dolor Tienen que cambiar esto de alguna manera.
Creo que acabo de encontrar una explicación de por qué esto no está funcionando para mi DLL y mi aplicación de prueba. Aquí está la excepción final del blog de algún tipo :
La solución para esto es asegurarse de que su aplicación y los ensamblajes de soporte tengan el mismo espacio de nombres o asegurarse de fusionar los contenidos de AppName.exe.config y DllName.dll.config (sí cuando compila un .dll ahora genera este archivo, sin embargo, se ignora si lo copias en el directorio de la aplicación y no se fusiona automáticamente)
Entonces, o tengo que mantener el DLL y la Aplicación en el mismo espacio de nombres -o-- Tengo que fusionar los contenidos del archivo de configuración DLL con el archivo de configuración de la Aplicación.
(¿Este tipo de derrota no tiene el propósito de la DLL? Pensé que se suponía que una DLL era una biblioteca independiente).
Quizás es por eso que funciona para mi compañero de trabajo. La aplicación de producción comparte el mismo espacio de nombres que la DLL. (Mi aplicación de prueba claramente no ...)
ACTUALIZACIÓN: Me acabo de sentar con mi compañero de trabajo recientemente y hablé sobre este problema de nuevo y parece que nunca funcionó para él tampoco, pero no se había dado cuenta porque había establecido el valor inicial para que fuera el mismo que el dispositivo que estábamos tratando de usar. Así que, por supuesto, pareció funcionar al principio, pero tan pronto como lo desplegamos en otro lugar con configuraciones ligeramente diferentes, se rompió nuevamente.
Es posible que en su DLL tenga el modificador de acceso (para Configuraciones1.Configuraciones) establecido en Interno (Friend for VB). Intente cambiar el Modem de Acceso a Público y vea si eso le permite a su aplicación leer / escribir valores de la configuración de dll.
El error que creo que todos ustedes hacen es que aparentemente hacen referencia a la configuración de DLL a través de Settings1.Default.IPAddress
mientras que simplemente se supone que deben hacer esto Settings1.IPAddress
.
La diferencia es que cuando usa Settings1.Default.IPAddress
los valores se obtienen de los valores codificados en el archivo de ensamblaje (.dll o .exe) como Attribute [global :: System.Configuration.DefaultSettingValueAttribute (...)].
Mientras Settings1.IPAddress
es el valor que se puede editar en el archivo .dll.config
(archivo XML) **. por lo tanto, cualquier cambio que realice en el archivo XML no se reflejará en el valor predeterminado codificado en el conjunto.
No esta:
IP = IPAddress.Parse(Settings1.Default.IPAddress);
Pero prueba esto:
*IP = IPAddress.Parse(Settings1.IPAddress);
La respuesta de Howard cubre la teoría.
Una forma rápida y sucia de resolver esto es analizar manualmente el archivo de configuración xml.
string configFile = Assembly.GetExecutingAssembly().Location + ".config";
XDocument.Load(configFile).Root.Element("appSettings")....