From my experience the easiest thing to do is programmatically load an app.config from a known location.
Add an app.config for your test project, and populate it as required, then add the following code to the ClassInitialize method on any test class that requires the app.config.
var map = new ExeConfigurationFileMap();
map.ExeConfigFilename = @"C:\Development\Tests\WcfUtilities\ClientApplication\App.config";
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
Showing posts with label Config. Show all posts
Showing posts with label Config. Show all posts
Monday, May 20, 2013
Friday, January 27, 2012
Using IoC for Extensibility
MEF is probably a better choice if you know up front there is a good likelihood of consumers wanting to extend your application by injecting their own types. However, I think there are a few exceptions to this rule.
Firstly, most modern software applications make extensive use of IoC to loosely couple dependencies and allow easy unit testing. Also, sometimes you don't think it is likely someone will want to swap out a class, but don't want to rule it out either. Building in MEF support for unlikely cases is a waste of time in my opinion, especially if there are ways to override behaviour using the IoC mechanisms you're already using. In these cases I prefer to allow consumers to override the IoC registered types.
I did a post some time ago on how to prevent IoC configuration chaos (refering to the explosion in size of your app.config if you put all registrations in it). This post discusses using code registrations and a mechanism to automatically run the registration code for each assembly on start-up.
This idea can be extended to allow custom extensions to be added.
By default Unity doesn't allow types to be registered that are not referenced by the application (I think Structure Map doesn't allow this either).
Scenario 1)
A consumer of an application that is already fully completed wants to change some behaviour in that application, and they do not have the source code, just the binaries. The application uses the IoC pattern referenced by the blog post above.
The consumer can create a new application project that references everything the original application and basically wraps around it. The new application includes any new references required to new assemblies containing classes you want to use in IoC registration. On start-up the new application simply delegates into the original. Now you can customise the IoC mappings in the App.Config of the new application. This works great for windows services, web services, console applications, and some UI applications. This is the preferable scenario.
Scenario 2)
Another option is to customise the IoC pattern described in the blog post mentioned above. When the initialisation process is looking referenced assemblies in the AppDomain, you can add some IO code to scan for assemblies in a folder. These new assemblies can be loaded with reflection and added into the AppDomain. Once this initialisation process is complete the App.Config can be applied. This is less desirable because the author of the original application has little control over how customisation are used by the original system. Potentially a security risk.
You could modify the reflection assembly loading mechanism to only allow assemblies with a certain signing key for example to mitigate this security concern.
Firstly, most modern software applications make extensive use of IoC to loosely couple dependencies and allow easy unit testing. Also, sometimes you don't think it is likely someone will want to swap out a class, but don't want to rule it out either. Building in MEF support for unlikely cases is a waste of time in my opinion, especially if there are ways to override behaviour using the IoC mechanisms you're already using. In these cases I prefer to allow consumers to override the IoC registered types.
I did a post some time ago on how to prevent IoC configuration chaos (refering to the explosion in size of your app.config if you put all registrations in it). This post discusses using code registrations and a mechanism to automatically run the registration code for each assembly on start-up.
This idea can be extended to allow custom extensions to be added.
By default Unity doesn't allow types to be registered that are not referenced by the application (I think Structure Map doesn't allow this either).
Scenario 1)
A consumer of an application that is already fully completed wants to change some behaviour in that application, and they do not have the source code, just the binaries. The application uses the IoC pattern referenced by the blog post above.
The consumer can create a new application project that references everything the original application and basically wraps around it. The new application includes any new references required to new assemblies containing classes you want to use in IoC registration. On start-up the new application simply delegates into the original. Now you can customise the IoC mappings in the App.Config of the new application. This works great for windows services, web services, console applications, and some UI applications. This is the preferable scenario.
Scenario 2)
Another option is to customise the IoC pattern described in the blog post mentioned above. When the initialisation process is looking referenced assemblies in the AppDomain, you can add some IO code to scan for assemblies in a folder. These new assemblies can be loaded with reflection and added into the AppDomain. Once this initialisation process is complete the App.Config can be applied. This is less desirable because the author of the original application has little control over how customisation are used by the original system. Potentially a security risk.
You could modify the reflection assembly loading mechanism to only allow assemblies with a certain signing key for example to mitigate this security concern.
Thursday, November 25, 2010
App.Config files vs INI files vs Registry
Here's a couple of links I have found on the topic:
- http://blogs.msdn.com/b/oldnewthing/archive/2007/11/26/6523907.aspx
This covers it pretty well. Seems to me that by default look to app.config files first, unless central management of windows app.config is important to your application; in which case consider registry. Data that needs to be secured should never really be in config, a database is a far better candidate for this sensitive data. - http://stackoverflow.com/questions/2475811/app-config-vs-ini-files
Monday, April 19, 2010
Preventing IoC Configuration Chaos
After working with tightly coupled (read as "welded") existing code bases in many previous companies, when given a green fields opportunity, I want to ensure thorough use of IoC. This is essential to allow automated testing. Automated testing is essential for efficient agile development.
The problem is, when you write a large system, that equates to a large config file. Actually it will be an enormous config file. This is unacceptable in my opinion for several reasons:
The problem is, when you write a large system, that equates to a large config file. Actually it will be an enormous config file. This is unacceptable in my opinion for several reasons:
- Large XML / Config files are annoying to maintain, and easy to get wrong.
- There's no compile time checking and fast feedback for XML / Config files.
- Most of the time the config is static, no one will want to change it at runtime for a production system (excluding unit testing).
- The config is owned and stored in the app/web config but some of your DLL's are designed to be reused independently and whenever they are consumers need to find an example of config and copy and paste it.
Nasty.
So a good solution needs the following attributes:
- By default (with no consumer code or config) any individual DLL must own its own default config. If a consumer takes and consumes your DLL that's all they need.
- By default the IoC container must be preconfigured to return production instances.
- Any hard coded default must be override-able by config.
- It must be easy to trigger IoC container intitialisation on application startup.
- Ideally the consumer shouldn't have to maintain a list of DLL's to intitialise.
Here's some sample code that I have come up with that attempts to solves these with StructureMap.
The basic idea is that all interfaces and abstracts registered with IoC for the primary purpose of unit testing should be configured with code in a DLL specific "Startup" class. Each Referenced assembly in the current AppDomain is "visited" using a psuedo-visitor pattern and its Startup class is located and executed.
Each assembly that contains IoC registrations that need to evaluated must be decorated with this custom attribute.
[assembly: AssemblyInitialization(typeof(MamalsStartup))]This points to the startup class containing the code registrations. Here's an example of a Startup implementation:public class MamalsStartup : IStartup { private readonly object syncRoot = new object(); public bool IsInitialized { get; private set; } public void InitializeObjectFactory() { if (this.IsInitialized) { return; } lock (this.syncRoot) { if (this.IsInitialized) { return; } var factory = ObjectFactory.Container; factory.Configure(config => { config.For<ICat>().Use<Cat>(); config.For<ICat>().Use<Cat>().Named("Felix").OnCreation(c => c.Name = "Felix"); config.For<IDog>().Use<Dog>(); config.For<IChapter>().Use<Chapter1>(); }); FrameworkInitialise.ObjectFactoryInitializeCompleted += this.OnObjectFactoryInitializeCompleted; this.IsInitialized = true; } } public void Shutdown() { // Trigger any shutdown / cleanup logic } private void OnObjectFactoryInitializeCompleted(object sender, System.EventArgs e) { // You can do any singleton registration here. Or any registrations that require other registrations have been completed. FrameworkInitialise.ObjectFactoryInitializeCompleted -= this.OnObjectFactoryInitializeCompleted; } }Notice how I have made an event that fires once all IStartup.InitializeObjectFactory this is to allow complex registrations that require instances of standard objects or singletons to be available. It also useful for kicking off any other intialisation that may be required. There's also a ShutDown method, this is useful for tidying up any singleton registrations that implement IDisposable or other cleanup logic.
To trigger the whole process the consuming code only needs one line of code:
// Invoke Initialise to trigger the process of "visiting" all assemblies referenced and calling each assemblies
// startup class to configure the IoC container.
FrameworkInitialise.Initialise();
Here's the initialize method:
/// <summary>
/// Initializes the AppDomain assemblies that have the <see cref="AssemblyInitializationAttribute"/>.
/// </summary>
public static void Initialize()
{
if (isInitialised)
{
return;
}
isInitialised = true;
var current = AppDomain.CurrentDomain;
current.AssemblyLoad += OnAssemblyLoad;
current.ProcessExit += ProcessExit;
var assemblies = (from assemblyName in Assembly.GetEntryAssembly().GetReferencedAssemblies()
where assemblyName.FullName.StartsWith(AssemblyPrefix, StringComparison.InvariantCultureIgnoreCase)
select Assembly.Load(assemblyName))
.AsParallel();
var list = new Dictionary<int, AssemblyInitializationAttribute>();
FindInitAttribute(assemblies, list);
// Finding and accessing the AssemblyInitializationAttribute will instantiate it and its ctor will trigger that assembly's startup class.
// By the time this point is reached all assemblies have had their Object Factories configured.
var handler = ObjectFactoryInitializeCompleted;
if (handler != null)
{
// Some Assemblies may be interested to be informed when all others have had their Object Factories configured.
// This will allow them to perform any other intialisation code that requires dependent assemblies to be configured first.
handler(null, EventArgs.Empty);
}
}
Subscribe to:
Posts (Atom)