app.config para una biblioteca de clases

83

No puedo ver un archivo app.config generado para una biblioteca de clases por el asistente VS2008. En mi investigación encontré que en una aplicación solo existe una app.config.

¿Es malo agregar un app.config manualmente a una biblioteca de clases o existen otros métodos que sirvan para el propósito de un app.config en la biblioteca de clases?

Necesito almacenar la información de configuración de log4net dentro del archivo app.config.

logeeks
fuente
3
Puede leer el archivo de configuración de su proyecto ejecutable desde su biblioteca.
Akram Shahda

Respuestas:

102

Por lo general, no debe agregar un app.configarchivo a un proyecto de biblioteca de clases; no se usará sin doblar y torcer dolorosamente de su parte. No daña el proyecto de la biblioteca en absoluto, simplemente no hará nada en absoluto.

En su lugar, configura la aplicación que está usando su biblioteca; por lo que la información de configuración requerida iría allí. Es probable que cada aplicación que pueda usar su biblioteca tenga diferentes requisitos, por lo que esto también tiene sentido lógico.

Andrew Barber
fuente
23
Bien por usted. Sin embargo, no estaba respondiendo a tu pregunta. Claramente, tiene algún tipo de sistema de configuración de cosecha propia que no se aplica a la persona que hace la pregunta aquí.
Andrew Barber
1
Tengo una biblioteca de clases Selenium WebDriver que ejecuto desde NUnit para todos mis casos de prueba. Prefiero no tener que preocuparme por configurar la configuración en NUnit. ¿Cómo puedo doblar y torcer para hacer esto? :-)
MacGyver
3
Lo resolví ... Si usa NUnit, nombre su archivo app.config con el mismo nombre que su nombre de archivo de proyecto * .nunit. Entonces, por ejemplo, si llamó a su proyecto "ClassLibraryA.nunit", entonces nombre el archivo de configuración de la biblioteca de clases "ClassLibraryA.config". También deben residir en la misma carpeta / directorio. NUnit realmente está usando esto como el archivo de configuración principal .... agregue una referencia a System.Configuration (en la pestaña .NET) .... y use este código: string settingValue = ConfigurationManager.AppSettings ["settingName"];
MacGyver
2
¿Cómo recomendaría configurar las cosas al realizar pruebas de integración? Para mí, parece lógico tener un app.config en esa biblioteca de prueba con la cadena de conexión.
Tomas Jansson
2
¿Qué sucede si no puede configurar la aplicación porque no es de su propiedad?
Pico de voltaje
50

No sé por qué aún no se ha dado esta respuesta:

En general, diferentes personas que llaman a la misma biblioteca utilizarán diferentes configuraciones. Esto implica que la configuración debe residir en la aplicación ejecutable y no en la biblioteca de clases.

Puede crear una app.config dentro del proyecto de biblioteca de clases. Contendrá configuraciones predeterminadas para los elementos que cree dentro de la biblioteca. Por ejemplo, contendrá cadenas de conexión si crea un modelo de Entity Framework dentro de la biblioteca de clases.

Sin embargo, esta configuración no será utilizada por la aplicación ejecutable que llame a la biblioteca. En su lugar, estas configuraciones se pueden copiar del archivo library.dll.config al app.config o web.config de la persona que llama, de modo que se puedan cambiar para que sean específicas de la persona que llama y del entorno en el que se encuentra la persona que llama. desplegada.

Así ha sido con .NET desde el primer día.

John Saunders
fuente
2
Pero, ¿qué debo hacer si necesito llamar a la funcionalidad del servicio web desde la biblioteca de clases? VS creó una aplicación.config predeterminada, pero mi aplicación se bloqueó al intentar llamar a la función de servicio web; no puede encontrar entradas de configuración ...
Laserson
Debe copiar los elementos que se colocaron en la biblioteca de clases app.config en app.config o web.config del llamador de la biblioteca de clases. Esto permite que la persona que llama tenga el control de la configuración. Por ejemplo, la persona que llama ahora puede cambiar la URL del servicio al que llama su biblioteca de clases, y su biblioteca de clases ni siquiera sabrá sobre el cambio.
John Saunders
6
@John Saunders: "puede necesitar" son exactamente las palabras correctas. Por lo tanto, puede haber situaciones en las que los ajustes de configuración difieran solo por servidor (por ejemplo, cadenas de conexión) y es más conveniente que la dll tenga su propia configuración que copiarla muchas veces para cada ensamblado que use la dll. En mi opinión, el uso preferido de Microsofts / .NET no es un santo grial. Depende realmente de lo que sea más conveniente en un escenario de implementación. No hay necesidad de regañar a Todd, su opinión es tan importante como la suya o la de Microsofts.
Estoy realmente interesado en esta solución, me parece ideal. Tiene sentido que la biblioteca tenga configuraciones predeterminadas, mientras que la aplicación podría anularlas. ¿Ampliaría sobre cómo se puede propagar la configuración desde el archivo app.config de la biblioteca al archivo app.config del ensamblado en ejecución, o me dirigiría a un recurso relevante?
aplastar
@crush: Se llama "copiar y pegar". La función de configuración fuertemente tipada de .NET puede ayudar un poco, ya que integra valores predeterminados en el ensamblaje.
John Saunders
43

Jon, se han dado muchas opiniones que no respondieron correctamente a tu pregunta.

Le daré MI OPINIÓN y luego le diré cómo hacer exactamente lo que pidió.

No veo ninguna razón por la que un ensamblado no pueda tener su propio archivo de configuración. ¿Por qué el primer nivel de atomicidad (¿es una palabra real?) Está en el nivel de la aplicación? ¿Por qué no a nivel de solución? Es una decisión arbitraria, acertada y, como tal, una OPINIÓN. Si tuviera que escribir una biblioteca de registro y quisiera incluir un archivo de configuración para ella, que se usaría globalmente, ¿por qué no podría conectarse a la funcionalidad de configuración incorporada? Todos lo hemos hecho ... hemos intentado proporcionar una funcionalidad "potente" a otros desarrolladores. ¿Cómo? Haciendo suposiciones que se traducen inherentemente en restricciones. Eso es exactamente lo que hizo MS con el marco de configuración, así que tienes que "engañarlo" un poco.

Para responder directamente a su pregunta, simplemente agregue el archivo de configuración manualmente (xml) y asígnele un nombre que coincida con su biblioteca e incluya la extensión "config". Ejemplo:

MyDomain.Mylibrary.dll.Config

A continuación, utilice ConfigurationManager para cargar el archivo y acceder a la configuración:

string assemblyPath = new Uri(Assembly.GetExecutingAssembly().CodeBase).AbsolutePath;
Configuration cfg = ConfigurationManager.OpenExeConfiguration(assemblyPath);
string result = cfg.AppSettings.Settings["TEST_SETTING"].Value;

Tenga en cuenta que esto es totalmente compatible con la jerarquía machine.config, aunque haya elegido explícitamente el archivo de configuración de la aplicación. En otras palabras, si la configuración no está allí, se resolverá más alto. La configuración también anulará las entradas de machine.config.

Todd Beaulieu
fuente
3
-1: Tu opinión, per se, no es importante. Los hechos serían importantes. .NET, desde el día 1, se creó para que los llamadores de una biblioteca determinen la configuración de los elementos dentro de la biblioteca. Es lo único que tiene sentido real para la configuración, ya que diferentes personas que llaman a la biblioteca pueden necesitar configuraciones diferentes.
John Saunders
19
@JohnSaunders "diferentes personas que llaman a la biblioteca pueden necesitar configuraciones diferentes". Exactamente, "pueden" necesitar configuraciones diferentes, y su lógica tiene perfecto sentido en todos los casos en los que la configuración depende de la persona que llama. Pero hay varios casos en los que la configuración se usa internamente para la biblioteca de clases, y la configuración es exactamente la misma, sin importar quién sea la persona que llama. Si tiene 10 aplicaciones que consumen una biblioteca, tiene que ser peor copiar y pegar exactamente la misma configuración en 10 archivos de configuración.
wired_in
3
@ToddBeaulieu: Creo que la palabra que quieres es 'atomicidad'.
nicodemus13
3
En una arquitectura de complementos, tiene sentido si todos los complementos tienen su propio archivo de configuración.
Davatar
4
@RMuesi Noone dijo que nunca cambia, solo que no depende de la persona que llama a la biblioteca. La configuración puede cambiar dependiendo de si está depurando la biblioteca frente a una versión de producción. Se puede cambiar en función del entorno en el que está construyendo para, etc
wired_in
6

De hecho, la biblioteca de clases que está implementando está recuperando información de app.config dentro de la aplicación que la consume, por lo que la forma más correcta de implementar la configuración para las bibliotecas de clases en .net en VS es preparar app.config en el aplicación para configurar todo lo que consume, como la configuración de bibliotecas.

He trabajado un poco con log4net, y descubrí que el que preparaba la aplicación siempre tenía una sección para la configuración de log4net dentro de main app.config .

Espero que encuentre esta información útil.

Nos vemos y publica comentarios sobre la solución que encontraste.

EDITAR:

En el siguiente enlace tiene una aplicación.config con la sección para log4net:

http://weblogs.asp.net/tgraham/archive/2007/03/15/a-realistic-log4net-config.aspx

Amedio
fuente
2
+1 Exactamente; El app.configse carga desde el programa real que eventualmente se ejecuta ... no desde las bibliotecas de clases individuales. Francamente, es un poco confuso cuántos no conocen este hecho tan básico.
Andrew Barber
Tal vez la gente provenga del lenguaje Java y allí tenga un log4java.properties y un archivo de propiedades separado para su aplicación.
Amedio
6

Si desea configurar el registro de su proyecto usando log4Net, mientras usa una biblioteca de clases, no hay necesidad real de ningún archivo de configuración. Puede configurar su registrador log4net en una clase y puede usar esa clase como biblioteca.

Como log4net ofrece todas las opciones para configurarlo.

Encuentre el código a continuación.

public static void SetLogger(string pathName, string pattern)
        {
            Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();

            PatternLayout patternLayout = new PatternLayout();
            patternLayout.ConversionPattern = pattern;
            patternLayout.ActivateOptions();

            RollingFileAppender roller = new RollingFileAppender();
            roller.AppendToFile = false;
            roller.File = pathName;
            roller.Layout = patternLayout;
            roller.MaxSizeRollBackups = 5;
            roller.MaximumFileSize = "1GB";
            roller.RollingStyle = RollingFileAppender.RollingMode.Size;
            roller.StaticLogFileName = true;
            roller.ActivateOptions();
            hierarchy.Root.AddAppender(roller);

            MemoryAppender memory = new MemoryAppender();
            memory.ActivateOptions();
            hierarchy.Root.AddAppender(memory);

            hierarchy.Root.Level = log4net.Core.Level.Info;
            hierarchy.Configured = true;
      }

Ahora, en lugar de llamar a XmlConfigurator.Configure (new FileInfo ("app.config")), puede llamar directamente a SetLogger con la ruta y el patrón deseados para configurar el registrador en la función de inicio de la aplicación Global.asax.

Y use el siguiente código para registrar el error.

        public static void getLog(string className, string message)
        {
            log4net.ILog iLOG = LogManager.GetLogger(className);
            iLOG.Error(message);    // Info, Fatal, Warn, Debug
        }

Al usar el siguiente código, no necesita escribir una sola línea ni en la aplicación web.config ni dentro de la aplicación.config de la biblioteca.

Rahul
fuente
2
sentí que esta es la mejor respuesta ... en lugar de discutir si se debe permitir el archivo de configuración para una biblioteca ... esta respuesta responde a la pregunta del OP sobre el uso de Log4net
saurav
1
Aunque la pregunta usó log4net como ejemplo, la pregunta real es acerca de las configuraciones en general. Yo diría que las respuestas sobre log4net son en realidad irrelevantes.
binki
4

En realidad, en algunos casos excepcionales, puede almacenar app.config en bibliotecas de clases (agregando manualmente) y analizarlo mediante OpenExeConfiguration .

 var fileMap =
    new ExeConfigurationFileMap {ExeConfigFilename = 
    @"C:\..somePath..\someName.config"};
 System.Configuration.Configuration config =
    ConfigurationManager.OpenMappedExeConfiguration(fileMap, 
    ConfigurationUserLevel.None);

Realmente debería estimar la necesidad real de esto. Para datos abstractos no es la mejor solución, ¡pero las "Secciones de configuración" podrían ser muy útiles!

Por ejemplo, organizamos nuestra arquitectura WCF de N-Tier desacoplada, sin metadatos, simplemente usando Unity Container e Injection Factory basados ​​en Channel Factory T. Agregamos dll de ClassLibrary externos con solo [Service Contract] Interfaces y app.config común en orden para leer los puntos finales de la sección del cliente y agregarlos / cambiarlos fácilmente en un solo lugar.

Roma Borodov
fuente
3

Desea agregar App.config a su biblioteca de clases de pruebas , si está utilizando un trazador / registrador. De lo contrario, no se registra nada cuando ejecuta la prueba a través de un corredor de prueba como TestDriven.Net.

Por ejemplo, lo uso TraceSourceen mis programas, pero la ejecución de pruebas no registra nada a menos que agregue un archivo App.config con la configuración de seguimiento / registro a la biblioteca de clases de prueba también.

De lo contrario, agregar App.config a una biblioteca de clases no hace nada.

Daniel AA Pelsmaeker
fuente
2

Su respuesta para una creación no manual de un app.config es la pestaña Propiedades / Configuración del proyecto de Visual Studio.

Cuando agrega una configuración y la guarda, su app.config se creará automáticamente. En este punto, se genera un montón de código en un espacio de nombres { yourclasslibrary .Properties } que contiene las propiedades correspondientes a su configuración. La configuración en sí se colocará en la configuración de applicationSettings de app.config.

 <configSections>
    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
        <section name="ClassLibrary.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    </sectionGroup>
</configSections>
<applicationSettings>
    <ClassLibrary.Properties.Settings>
        <setting name="Setting1" serializeAs="String">
            <value>3</value>
        </setting>
    </BookOneGenerator.Properties.Settings>
</applicationSettings>

Si agregó una configuración de ámbito de aplicación llamada Configuración1 = 3, se creará una propiedad llamada Configuración1. En la compilación, estas propiedades se están convirtiendo en parte del binario y están decoradas con un DefaultSettingValueAttribute que se establece en el valor que especificó en el momento del desarrollo.

     [ApplicationScopedSetting]
    [DebuggerNonUserCode]
    [DefaultSettingValue("3")]
    public string Setting1
    {
        get
        {
            return (string)this["Setting1"];
        }
    }

Por lo tanto, como en el código de su biblioteca de clases, hace uso de estas propiedades, si no existe una configuración correspondiente en el archivo de configuración de tiempo de ejecución, utilizará el valor predeterminado. De esa manera, la aplicación no fallará por no tener una entrada de configuración, lo cual es muy confuso la primera vez que no sabes cómo funcionan estas cosas. Ahora, se está preguntando cómo se puede especificar nuestro propio valor nuevo en una biblioteca implementada y evitar que se utilice el valor de configuración predeterminado.

Eso sucederá cuando configuremos correctamente el archivo app.config del ejecutable. Dos pasos. 1. le informamos que tendremos una sección de configuración para esa biblioteca de clases y 2. con pequeñas modificaciones pegamos el archivo de configuración de la biblioteca de clases en la configuración ejecutable. (hay un método en el que puede mantener el archivo de configuración de la biblioteca de clases externo y simplemente hacer referencia a él desde la configuración del ejecutable.

Entonces, puede tener un app.config para una biblioteca de clases, pero es inútil si no lo integra correctamente con la aplicación principal. Vea aquí lo que escribí hace algún tiempo: enlace

Mircea Ion
fuente
1

No se agrega automáticamente el archivo app.config cuando agrega un proyecto de biblioteca de clases a su solución.

Que yo sepa, no hay ninguna contraindicación sobre hacerlo manualmente. Creo que este es un uso común.

Acerca de la configuración de log4Net, no tiene que poner la configuración en app.config, puede tener un archivo conf dedicado en su proyecto, así como un archivo app.config al mismo tiempo.

este enlace http://logging.apache.org/log4net/release/manual/configuration.html le dará ejemplos sobre ambas formas (sección en app.config y archivo de configuración de log4net independiente)

Bruno
fuente
No hace daño agregar nada a un app.configproyecto de biblioteca, no. Pero tampoco se utilizará.
Andrew Barber
1
@AndrewBarber Se utilizará en un proyecto de prueba. Ver stackoverflow.com/a/31389495
binki
0

Recomendaría usar Properties.Settings para almacenar valores como ConnectionStrings y así sucesivamente dentro de la biblioteca de clases. Aquí es donde se almacenan todas las cadenas de conexión por sugerencia de Visual Studio cuando intenta agregar un adaptador de mesa, por ejemplo. ingrese la descripción de la imagen aquí

Y luego serán accesibles usando este código en todas partes de la biblioteca clas

var cs=  Properties.Settings.Default.[<name of defined setting>];
sishanov
fuente