Configuración.Por defecto. & Lt; propiedad > siempre devuelve el valor predeterminado en lugar del valor en el almacenamiento persistente (archivo XML)

StackOverflow https://stackoverflow.com/questions/192641

Pregunta

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 la IP de un ".dll.config". Archivo (XML): aparentemente, esto se genera automáticamente mediante la " Configuración de la aplicación " archivo que creó (Settings1.settings). El beneficio de esto fue permitir al usuario final cambiar la dirección IP en el archivo XML / config a voluntad.

Desafortunadamente, cuando verifico su código del árbol e intento compilar (o usar) este nuevo código, cualquier aplicación que llame a esta 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é a 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. Esto siempre sucederá si usa la configuración en un archivo dll.

  1. ¿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 ha hecho que esto funcione ...)

  2. Dado que mi marco parece no poder acceder o abrir el archivo de configuración, ¿cómo puedo averiguar por qué falla? ¿O incluso detectar cuándo sucede esto?

Decker : Eso ayuda un poco. Desafortunadamente, estoy escribiendo esta DLL a una especificación, por lo que en realidad no tengo acceso al archivo de configuración de la aplicación. Como notará anteriormente, mi compañero de trabajo creó una " Configuración 1 .settings " expediente. No entendí esto en ese momento, pero parece que ahora agrego el " 1 " lo mantiene fuera del espacio de configuración de cualquier aplicación que lo llame.

Supongo que lo que estoy tratando de averiguar es por qué la DLL no parece encontrar el archivo de configuración junto a él en el mismo directorio. El rastreo a través del código paso a paso no revela nada.

Como comentario aparte, puedo cambiar el " Tipo de salida " de mi montaje de " Biblioteca de clases " a " Aplicación de Windows " y agregue 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 que puedo alterar y hacer que extraiga los nuevos datos del archivo. Entonces estoy un poco confundido. ¿Alguna idea?

¿Fue útil?

Solución

Estoy abordando este problema exacto en una aplicación que estoy en medio de la creación de prototipos. Aunque la sugerencia de Decker de hackear los archivos de configuración juntos debería funcionar, creo que este es un hack 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 en que .Net maneja estos archivos app.config.

Otros consejos

Utilizo esta técnica todo el tiempo. A menudo tengo un ensamblaje de biblioteca que requiere ciertas configuraciones, y necesito que se configuren probando proyectos, así como el ejecutable principal "". ensamblados, ya sean proyectos web o proyectos de servicio de Windows.

Tienes razón en que cuando creas un archivo de configuración para cualquier proyecto, agrega un archivo de configuración de la aplicación. El valor que ingrese 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 desea hacer es copiar la sección de configuración del archivo app.config del proyecto de ensamblaje de la biblioteca y fusionarla (cuidadosamente) en el web.config o app.config correspondiente 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 " verdadero " archivo de configuración.

He tenido este mismo problema durante mucho tiempo, es molesto.

Me gusta la idea de hacer su propio archivo de configuración y hacer que cada DLL lo analice, aunque aún podría ser fácil pasar por alto tener que cambiar la configuración.

Una cosa que he hecho en el pasado para al menos hacer esto un poco más fácil es asegurarme de que los valores de configuración del archivo Setting1.Settings no sean válidos.

Por ejemplo, tengo una clase que usa LINQ-To-SQL para hablar con la base de datos. 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 de desarrollo.

Una vez que haya creado el archivo DBML basado en 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 esa manera, si usa la DLL en otro proyecto y luego olvida fusionar los archivos de configuración para agregar el valor de configuración adecuado para la DLL, al menos obtendrá un error que dice algo como "No se puede conectar a FAKE_DATABASE " ;.

Por supuesto, si tiene que volver a trabajar con el diseñador, deberá volver a cambiar el valor al valor de su base de datos de desarrollo.

Gran dolor. Tienen que cambiar esto de alguna manera.

Aparentemente, su aplicación está intentando leer desde el archivo de configuración predeterminado (que probablemente sea el archivo de configuración de la aplicación). Para asegurarse, agregue el par clave-valor en el archivo de configuración de la DLL al archivo de configuración de la aplicación, ejecute la aplicación y vea si se lee esta vez.

Creo que acabo de encontrar una explicación de por qué esto no funciona para mi DLL y mi aplicación de prueba. Aquí está la excepción final de el blog de algún chico :

  

La solución para esto es asegurarse de que su aplicación y los ensamblados de soporte tengan el mismo espacio de nombres o asegurarse de fusionar el contenido de AppName.exe.config y DllName.dll.config (sí, cuando compila un .dll ahora genera este archivo, sin embargo, se ignora si lo copia al directorio de la aplicación y no se fusiona automáticamente)

Entonces, o bien tengo que mantener la DLL y la Aplicación en el mismo espacio de nombres, o bien, tengo que fusionar el contenido del archivo de configuración de DLL con el archivo de configuración de la Aplicación.

(¿No es esto una especie de derrota 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: Hace poco me senté con mi compañero de trabajo y volví a hablar sobre este problema y parece que tampoco le funcionó, pero no se había dado cuenta porque había configuramos el valor inicial para que sea el mismo que el dispositivo que estábamos tratando de usar. Entonces, por supuesto, parecía funcionar al principio, pero tan pronto como lo implementamos en otro lugar con configuraciones ligeramente diferentes, se rompió nuevamente.

He visto un problema similar al usar app.config. Intente ejecutar su aplicación desde .exe en lugar de desde Visual Studio & amp; ver si se comporta como se esperaba.

Es posible que en su DLL tenga el modificador de acceso (para la Configuración1. Configuración) configurado en Interno (Amigo para VB). Intente cambiar el modificador de acceso a público y vea si eso permite que su aplicación lea / escriba valores de la configuración de dll.

La respuesta de Howard cubre la teoría.

Una forma rápida y sucia de resolver esto es analizar el archivo de configuración xml manualmente.

    string configFile = Assembly.GetExecutingAssembly().Location + ".config";
    XDocument.Load(configFile).Root.Element("appSettings")....

El error que creo que todos cometen es que aparentemente hacen referencia a la configuración de DLL a través de Settings1.Default.IPAddress mientras simplemente se supone que debes hacer esto Settings1.IPAddress .

La diferencia es que cuando utiliza Settings1.Default.IPAddress los valores se obtienen de los valores codificados incorporados en el archivo de ensamblaje (.dll o .exe) como Atributo [global :: System. Configuration.DefaultSettingValueAttribute (...)].

Mientras Settings1.IPAddress es el valor que se puede editar en el archivo .dll.config (archivo XML) **. así que cualquier cambio que realice en el archivo XML no se refleja en el valor predeterminado codificado en el ensamblaje.

No esto:

IP = IPAddress.Parse(Settings1.Default.IPAddress);

Pero intente esto:

*IP = IPAddress.Parse(Settings1.IPAddress);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top