using multiple app.config files - c#

I have a console application that loads other libraries (DLL's). I'm using Spring.NET. My console application is very simple, load the app.config that is configured through DI to initialize the chosen library.
Code
ContextRegistry.GetContext();
Configuration (app.config)
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="spring">
<section name="context"
type="Spring.Context.Support.ContextHandler, Spring.Core"/>
<section name="objects"
type="Spring.Context.Support.DefaultSectionHandler, Spring.Core"/>
</sectionGroup>
</configSections>
<spring>
<context>
<resource uri="config://spring/objects"/>
<resource uri="assembly://MyDLL/MyDLL.Config/Services.xml"/>
</context>
<objects xmlns="http://www.springframework.net"
xmlns:aop="http://www.springframework.net/aop">
</objects>
</spring>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup></configuration>
Each library has its own "services.xml" file. These libraries also use Spring.NET.
<objects xmlns="http://www.springframework.net"
xmlns:aop="http://www.springframework.net/aop">
<object id="componentObj"
type="MyDLL.Services.ComponentService, MyDLL"
singleton="true" />
<object
id="componentServiceHost"
type="Spring.ServiceModel.Activation.ServiceHostFactoryObject, Spring.Services">
<property name="TargetName"
value="componentObj" />
</object>
</objects>
Getting a excpetion "Process is terminated due to StackOverflowException." If I comment out the <object id="componentServiceHost", the exception does not occur.
The VS console in debug shows
A first chance exception of type 'System.InvalidOperationException' occurred in System.ServiceModel.dll
A first chance exception of type 'Spring.Objects.Factory.ObjectCreationException' occurred in Spring.Core.dll
A first chance exception of type 'Spring.Objects.Factory.ObjectCreationException' occurred in Spring.Core.dll
Managed (v4.0.30319)' has exited with code -2147023895 (0x800703e9).

You can also place spring configuration in plain xml files and include those with your library. This way, you can easily share this configuration without the need of sharing an app.config.
You do have to explicitly reference this configuration file in the configuration of your host console application, but that's no duplication. The app.config of your console application host will look like this:
...
<spring>
<context>
<resource uri="file://services.xml"/>
<resource uri="assembly://MyAssembly/MyDataAccess/data-access.xml"/>
</context>
</spring>
See the spring.net docs how to configure a configuration in xml.

Related

Facing issue while running feature, specflow in visual studio, build error

I have created a basic feature file and trying to execute my first program. I have installed all mandatory packages through NuGet.
Error received :
Error The "GenerateFeatureFileCodeBehindTask" task failed unexpectedly.
System.Exception: Error when reading project file. ---> System.Configuration.ConfigurationErrorsException: Unrecognized element 'unitTestProvider'.
at System.Configuration.ConfigurationElement.DeserializeElement(XmlReader reader, Boolean serializeCollectionKey)
at System.Configuration.ConfigurationSection.DeserializeSection(XmlReader reader)
at TechTalk.SpecFlow.Configuration.ConfigurationSectionHandler.CreateFromXml(String xmlContent)
at TechTalk.SpecFlow.Configuration.ConfigurationLoader.Load(SpecFlowConfiguration specFlowConfiguration, ISpecFlowConfigurationHolder specFlowConfigurationHolder)
at TechTalk.SpecFlow.Generator.Configuration.GeneratorConfigurationProvider.LoadConfiguration(SpecFlowConfiguration specFlowConfiguration, SpecFlowConfigurationHolder specFlowConfigurationHolder)
at TechTalk.SpecFlow.Generator.Configuration.GeneratorConfigurationProviderExtensions.LoadConfiguration(IGeneratorConfigurationProvider configurationProvider, SpecFlowConfigurationHolder configurationHolder)
at TechTalk.SpecFlow.Generator.Project.ProjectReader.ReadSpecFlowProject(String projectFilePath, String rootNamespace)
--- End of inner exception stack trace ---
at TechTalk.SpecFlow.Generator.Project.ProjectReader.ReadSpecFlowProject(String projectFilePath, String rootNamespace)
at TechTalk.SpecFlow.Generator.Project.MSBuildProjectReader.LoadSpecFlowProjectFromMsBuild(String projectFilePath, String rootNamespace)
at SpecFlow.Tools.MsBuild.Generation.SpecFlowProjectProvider.GetSpecFlowProject()
at SpecFlow.Tools.MsBuild.Generation.GenerateFeatureFileCodeBehindTaskExecutor.Execute()
at SpecFlow.Tools.MsBuild.Generation.GenerateFeatureFileCodeBehindTask.Execute()
at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext() specflowFramework
my app.config looks like:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<configSections>
<sectionGroup name="NUnit">
<section name="TestRunner" type="System.Configuration.NameValueSectionHandler" />
</sectionGroup>
<section name="specFlow" type="TechTalk.SpecFlow.Configuration.ConfigurationSectionHandler, TechTalk.SpecFlow" />
</configSections>
<specFlow>
<language feature="en-US" />
<unitTestProvider name="MSTest" />
</specFlow>
</configuration>
The unit test providers are not configured anymore in the app.config with SpecFlow 3. You have to use the appropriate NuGet package. Doc link: https://docs.specflow.org/projects/specflow/en/latest/Guides/UpgradeSpecFlow2To3.html#changes-to-how-unit-test-providers-are-configured
In your case, you have to add the SpecFlow.NUnit package to your project and adjust your app.config to
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<configSections>
<sectionGroup name="NUnit">
<section name="TestRunner" type="System.Configuration.NameValueSectionHandler" />
</sectionGroup>
<section name="specFlow" type="TechTalk.SpecFlow.Configuration.ConfigurationSectionHandler, TechTalk.SpecFlow" />
</configSections>
<specFlow>
<language feature="en-US" />
</specFlow>
</configuration>
The list of the correct NuGet package depending on your unit test runner is: https://docs.specflow.org/projects/specflow/en/latest/Installation/Unit-Test-Providers.html
Full disclosure: I am a developer and maintainer of SpecFlow and SpecFlow+

How to create a Spring object type Integer?

Could anyone please help me take a look at this issue since I can only create a Spring object type String? When I try to create another Spring object type, I get the below error
Error
Class Initialization method MessengerLyncSDK2013.Testcases.Test.UnitTest1.ClassInitialize threw exception. System.Configuration.ConfigurationErrorsException: System.Configuration.ConfigurationErrorsException: Error creating context 'spring.root': Error creating object with name 'serverPort' defined in 'config [D:\Working Projects\lync2013\MessengerLyncSDK2013\TestResults\thanh.viet.le_LGVN13307-WIN7 2014-03-17 11_17_21\Out\MessengerLyncSDK2013.DLL.config#spring/objects] line 9' : Could not resolve matching constructor. ---> Spring.Objects.Factory.ObjectCreationException: Error creating object with name 'serverPort' defined in 'config [D:\Working Projects\lync2013\MessengerLyncSDK2013\TestResults\thanh.viet.le_LGVN13307-WIN7 2014-03-17 11_17_21\Out\MessengerLyncSDK2013.DLL.config#spring/objects] line 9' : Could not resolve matching constructor..
Spring object in xml file
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core" />
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
</sectionGroup>
</configSections>
<spring>
<context>
<resource uri="config://spring/objects" />
</context>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
<object id="connectServer" type="string">
<constructor-arg value="server.com"/>
</object>
<object id="serverPort" type="System.Int32" factory-method="Copy">
<constructor-arg index="0">
<value>5222</value>
</constructor-arg>
</object>
</objects>
</spring>
</configuration>
For more details, I am using visual studio 2010 with C#.
Try it, note for factory-method="Parse":
<object id="MyInt" type="System.Int32" factory-method="Parse">
<constructor-arg index="0">
<value>123</value>
</constructor-arg>
</object>
See also: How do I create a spring .Net standalone object of type Int32 defined in the IOC context file?
You can create an object with all your configuration and then just inject it:
<object id="ServerConfig" type"...">
<property name="ServerPort" value="5222"/>
...
</object>
<object id="Server" type"...">
<!-- Constructor injection -->
<constructor-arg name="configuration" ref="ServerConfig"/>
<!-- OR Property injection -->
<property name="Configuration" ref="ServerConfig"/>
</object>

Split EnterpriseLibrary Block configurations into multiple files

Is it possible to split the configuration for an enterprise library block into multiple files?
For example: I have three assemblies and one hosting project. I want to store the entlib v6 Exception Handling Application Block (EHAB) configuration for each assembly in a separate config file located in the particular assembly.
The hosting project references the three assemblies:
assembly_X
ehabX.config
assembly_Y
ehabY.config
assembly_Z
ehabZ.config
Hosting project
using ehabX.config
using ehabY.config
using ehabZ.config
I already tried the following:
App.config in the hosting project:
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="enterpriseLibrary.ConfigurationSource" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ConfigurationSourceSection, Microsoft.Practices.EnterpriseLibrary.Common" requirePermission="true" />
</configSections>
<enterpriseLibrary.ConfigurationSource>
<sources>
<add name="ehabX" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common" filePath="ExceptionHandling\ehabX.config" />
<add name="ehabY" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common" filePath="ExceptionHandling\ehabY.config" />
<add name="ehabZ" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common" filePath="ExceptionHandling\ehabZ.config" />
</sources>
<redirectSections>
<add sourceName="ehabX" name="exceptionHandling" />
<add sourceName="ehabY" name="exceptionHandling" />
<add sourceName="ehabZ" name="exceptionHandling" />
</redirectSections>
</enterpriseLibrary.ConfigurationSource>
</configuration>
ehabX.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="exceptionHandling" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Configuration.ExceptionHandlingSettings, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling"/>
</configSections>
<exceptionHandling>
<exceptionPolicies>
<add name="Swallow NotImplementedException">
<exceptionTypes>
<add type="System.NotImplementedException, mscorlib" postHandlingAction="None" name="NotImplementedException"/>
</exceptionTypes>
</add>
</exceptionPolicies>
</exceptionHandling>
</configuration>
ehabY.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="exceptionHandling" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Configuration.ExceptionHandlingSettings, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling"/>
</configSections>
<exceptionHandling>
<exceptionPolicies>
<add name="Swallow ArgumentException">
<exceptionTypes>
<add type="System.ArgumentException, mscorlib" postHandlingAction="None" name="NotImplementedException"/>
</exceptionTypes>
</add>
</exceptionPolicies>
</exceptionHandling>
</configuration>
The ehabZ.config is omitted.
Using the EHAB with the policy "Swallow NotImplementedException" works fine. But if I try to use the policy "Swallow ArgumentException" defnied in ehabY.config I get this error message:
Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.ExceptionHandlingException: The policy with name 'Swallow ArgumentException' cannot be found. Exception handling aborted.
Any suggestions?
Unfortunately, there is nothing out of the box that will let you merge multiple configuration sources into one configuration set.
I think you can probably do what you want but you will have to do some coding. You'll need to read in the appropriate configuration sources and create a custom IConfigurationSource that will merge them all. Additive merge of different config sources? has an example of a MergeConfigurationSource that could help you.

Spring.net Context Hierarchies not working

Spring version : 2.0.0.40000
Runtime : .NET 4.5
Taking the example shown here
www.springframework.net/.../objects.html and in the API
http://springframework.net/docs/1.3..../webframe.html - ContextHandler
I have the following
Code:
<configSections>
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
<sectionGroup name="child">
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core"/>
</sectionGroup>
</sectionGroup>
</configSections>
<spring>
<objects xmlns="http://www.springframework.net">
<import resource="assembly://ProjectDLL/Config/Spring.xml"/>
</objects>
<child>
<objects xmlns="http://www.springframework.net">
<object name="eventLog"
type="System.Diagnostics.EventLog, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
>
<constructor-arg type="string" name="logName" value="v1" />
<constructor-arg type="string" name="machineName" value="." />
<constructor-arg type="string" name="source" value="v1" />
</object>
</objects>
</child>
<context name="Parent">
<resource uri="config://spring/objects"/>
<context name="child">
<resource uri="config://spring/child/objects"/>
</context>
</context>
</spring>
Calling
ContextRegistry.GetContext();
of any context names results in
Message --- Error creating context 'ChildContext': Errored while postprocessing an object factory.
I've tried all the various naming for including Child, ChildContext, Children, all resulting in the same error.
In my example, I use a resource file that contains my objects ( ), if I do not import my own XML file, it works but importing it means that the child does not work. If I define the child in the same xml file, I get "Error creating context 'Parent': There are multiple root elements"
I know this is most likely a configuration issue and would appreciate any help.
Having not fully understood the error I was getting or why, the workaround was to use "depends-on" for startup. The spring xsd defines quiet a few here http://www.springframework.net/xsd/spring-objects.xsd

ContextRegistry rootContextName is always null or empty

Using Spring.NET IoC to inject dependency objects into properties. The app is an Outlook plug-in.
The code:
IApplicationContext ctx = ContextRegistry.GetContext();
this.Property = (MyObject)ctx.GetObject("MyObject");
The Config:
<configuration>
<configSections>
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
</sectionGroup>
</configSections>
<spring>
<context>
<resource uri="config://spring/objects"/>
</context>
<objects xmlns="http://www.springframework.net">
<description></description>
<!--Business Logic Layer Binding Objects-->
<object name="MyObject"
type="Quadrant2.MSCRM.Recruit.OfficeAddins.Toolbar.BusinessLogic.Q2_Win_SearchClient_Logic, Quadrant2.MSCRM.Recruit.OfficeAddins.Toolbar.BusinessLogic">
<property name="SearchClientDAL" ref="DAL_SearchClient"/>
</object>
<!-- snip -->
This code was running fine for around 2 years and then we upgraded a few assemblies around Outlook to run in Outlook 2010 and some Ribbon modifications - nothing that should affect Spring.NET I think.
Started getting the "The context name passed to the GetContext method cannot be null or empty" exception thrown on the GetContext(); call. On closer inspection I noted that the rootContextName is null - fair call, explains the exception I thought.
Also noted that the code would run fine during debug but fail once it runs outside debug. Checked dll's, dependencies and configs are all in the right place during install.
"Force fed" GetContext(); a context name, "spring.root" as per debug session rootContextName value, and the exception goes away but IApplicationContext is returned null.
Any ideas or obvious issues here?

Categories