Loading from XML Configuration File

An example of XML configuration file can be found at IoCConfiguration_Overview.xml. This file is used in test project IoC.Configuration.Tests.

-The XML Configuration file is validated against XML schema file IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd (see XML Configuration File Schema). -A template XML Configuration file IoC.Configuration.Template.xml can be found in folder IoC.Configuration.Content, where the Nuget package IoC.Configuration is installed (see XML Configuration Template).

To load the IoC configuration from XML configuration file use method IoC.Configuration.DiContainerBuilder.DiContainerBuilder.StartFileBasedDi() as shown below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
using OROptimizer.Xml; // add this using statement to be able to use XmlDocument extensions (i.e., e.XmlDocument.SelectElements("/iocConfiguration/diManagers"), etc.)
// ...

using (var containerInfo =
        new DiContainerBuilder.DiContainerBuilder()
        .StartFileBasedDi(
            new FileBasedConfigurationParameters(
                new FileBasedConfigurationFileContentsProvider(
                    Path.Combine(Helpers.TestsEntryAssemblyFolder, "IoCConfiguration_Overview.xml")),
                // Provide the entry assembly folder. Normally this is the folder,
                // where the executable file is. However for test projects this might not
                // be the case. This folder will be used in assembly resolution.
                Helpers.TestsEntryAssemblyFolder,
                new LoadedAssembliesForTests())
            {
                AdditionalReferencedAssemblies = new string[]
                {
                    // List additional assemblies that should be added to dynamically generated assembly as references
                    Path.Combine(Helpers.GetTestFilesFolderPath(), @"DynamicallyLoadedDlls\TestProjects.DynamicallyLoadedAssembly1.dll"),
                    Path.Combine(Helpers.GetTestFilesFolderPath(), @"DynamicallyLoadedDlls\TestProjects.DynamicallyLoadedAssembly2.dll")
                },
                // Set the value of AttributeValueTransformers to list of
                // IoC.Configuration.AttributeValuesProvider.IAttributeValueTransformer instances
                // to change some xml attribute values when the xml configuration is loaded,
                // before the configuration is parsed.
                // Good example of implementation of IoC.Configuration.AttributeValuesProvider.IAttributeValueTransformer
                // is IoC.Configuration.Tests.FileFolderPathAttributeValueTransformer.
                AttributeValueTransformers = new IAttributeValueTransformer []
                {
                    new FileFolderPathAttributeValueTransformer()
                },
                ConfigurationFileXmlDocumentLoaded = (sender, e) =>
                {
                    // Replace some elements in e.XmlDocument if needed,
                    // before the configuration is loaded.
                    // For example, we can replace the value of attribute 'activeDiManagerName' in element
                    // iocConfiguration.diManagers to use a different DI manager (say
                    // switch from Autofac to Ninject).
                    Helpers.EnsureConfigurationDirectoryExistsOrThrow(e.XmlDocument.SelectElement("/iocConfiguration/appDataDir").GetAttribute("path"));
                    e.XmlDocument.SelectElements("/iocConfiguration/diManagers")
                        .First()
                        .SetAttributeValue("activeDiManagerName", "Autofac");
                }
            }, out _)
        // Note, most of the time we will need to call method WithoutPresetDiContainer().
        // However, in some cases, we might need to create an instance of IoC.Configuration.DiContainer.IDiContainer,
        // and call the method WithDiContainer(IoC.Configuration.DiContainer.IDiContainer diContainer) instead.
        // This might be necessary when using the IoC.Configuration to configure dependency injection in
        // ASP.NET Core projects.
        // An example implementation of IDIContainer is IoC.Configuration.Autofac.AutofacDiContainer in
        // Nuget package IoC.Configuration.Autofac.
        .WithoutPresetDiContainer()

        // Note, native and IoC.Configuration modules can be specified in XML configuration file, in
        // iocConfiguration/dependencyInjection/modules/module elements.
        // However, if necessary, AddAdditionalDiModules() and AddNativeModules() can be used to load additional
        // IoC.Configuration modules (instances of IoC.Configuration.DiContainer.IDiModule), as well
        // as native (e.g, Ninject or Autofac) modules.
        // Also, AddAdditionalDiModules() and AddNativeModules() can be called multiple times in any order.
        .AddAdditionalDiModules(new TestDiModule())
        .AddNativeModules(CreateModule<object>("Modules.Autofac.AutofacModule1",
            new ParameterInfo[] { new ParameterInfo(typeof(int), 5) }))
        .RegisterModules()
        .Start())
{
    var diContainer = containerInfo.DiContainer;

    // Once the configuration is loaded, resolve types using IoC.Configuration.DiContainer.IDiContainer
    // Note, interface IoC.Configuration.DiContainerBuilder.IContainerInfo extends System.IDisposable,
    // and should be disposed, to make sure all the resources are properly disposed of.
    var resolvedInstance = containerInfo.DiContainer.Resolve<SharedServices.Interfaces.IInterface7>();
}
  • Once the configuration is loaded into containerInfo variable of type IoC.Configuration.DiContainerBuilder.IContainerInfo, resolve types using property DiContainer in IoC.Configuration.DiContainerBuilder.IContainerInfo (the property is of type IoC.Configuration.DiContainer.IDiContainer).

  • Interface IoC.Configuration.DiContainerBuilder.IContainerInfo extends System.IDisposable.

  • Native and IoC.Configuration modules can be specified in XML configuration file, in iocConfiguration/dependencyInjection/modules/module elements. However, if necessary, use the following methods in IoC.Configuration.DiContainerBuilder.FileBased.IFileBasedDiModulesConfigurator to load additional IoC.Configuration modules (instances of IoC.Configuration.DiContainer.IDiModule), as well as native (e.g, Ninject or Autofac) modules:
    • IFileBasedDiModulesConfigurator.AddAdditionalDiModules(params IDiModule[] diModules)
    • IFileBasedDiModulesConfigurator.AddNativeModules(params object[] nativeModules)

    Note

    These methods can be called multiple times in any order. In other words, we can add some IoC.Configuration modules using AddAdditionalDiModules, then some native modules using AddNativeModules(), then some more IoC.Configuration modules using AddAdditionalDiModules.

Modifying XML Configuration at Runtime

The XML Configuration file can be modified at runtime by passing a delegate for parameter configurationFileXmlDocumentLoaded in method IoC.Configuration.DiContainerBuilder.StartFileBasedDi(IConfigurationFileContentsProvider configurationFileContentsProvider, string entryAssemblyFolder, ConfigurationFileXmlDocumentLoadedEventHandler configurationFileXmlDocumentLoaded = null).

This method loads the configuration file into an instance of System.Xml.XmlDocument object, and executes the delegate passed in parameter configurationFileXmlDocumentLoaded.

By the time the delegate is executed, System.Xml.XmlDocument object is not yet validated against the XML schema file IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd (this is done after the delegate is executed). Therefore, the changes to System.Xml.XmlDocument object should be done in such a way that the XML document is still valid against this schema file.

Example of modifying the XML document at runtime to replace the value of attribute activeDiManagerName in element /iocConfiguration/diManagers with Autofac is shown below (this is copied from the C# code above).

new DiContainerBuilder.DiContainerBuilder()
       .StartFileBasedDi(
            // Other parameters...
            (sender, e) =>
            {
                e.XmlDocument.SelectElements("/iocConfiguration/diManagers").First()
                     .SetAttributeValue("activeDiManagerName", "Autofac");
            })