Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Configure the DLL to be dynamically loaded and run

0.00/5 (No votes)
28 Feb 2006 1  
Dynamically load DLLs, configure them, and use different DLLs / stubs when unit testing and when using the production version.

Introduction

This article can be useful when unit testing application-layers. When unit testing, the output should be well known to be tested. This can be achieved with stubs. In the stub, you can create the output you want to let the test pass. Nonetheless, stubs should not be called within the production environment, of course. How then do we switch 'on' the stub when unit testing, and 'off' when being in production? This article describes a way of dynamically loading an assembly by configuring it in a config-file.

To use the demo, be sure to have NUnit installed.

Using the code

The main class to use is ServiceProviderFactory. This factory activates the DLLs in its Create method. Before it can do that, it has to be configured by calling the Configure method. This is usually done in the constructor. The following code demonstrates this:

ServiceProviderFactory.Configure(
ResourceHelper.GetResourceFile(typeof(WalletUt).Assembly, 
                               "configFile.xml"));

Note that it uses a resourceHelper. This helper loads resources embedded in the assembly. In the above line of code, the helper loads the config.xml file from the WalletUt-assembly.

An assembly can be created using the Create method on the name it's given in the config.xml file or its type. The following shows this:

IProcesLayer _wallet = (IProcesLayer) 
 ServiceProviderFactory.Create("Wallet");
IProcesLayer _wallet = (IProcesLayer) 
 ServiceProviderFactory.Create(typeof(IProcesLayer));

Internal workings

To use a specific format for the config.xml file, we can validate this against a schema. To create the schema, I first created the XML-file and then created the schema with the XSD tool, which is part of the Visual Studio environment. This schema can than be used together with XmlValidatingReader to validate the config.xml file. The following screenshot is a short view of making the schema with the XSD tool.

create the schema with tool XSD

The config.xml file contains ServiceProviders. A ServiceProvider is defined in the class ServiceProvider. This class contains the type ('namespace.class' 'assembly-name') of the assembly to load. It also has an InterfaceType which can be specified. This is useful to have an interface specified, and this interface can be in a different assembly as is done in the demo. This way, the interface can be shared among other projects, and therefore the assembly itself does not have to be referenced.

The ServiceProvider contains an InitializeData parameter which is useful to pass on some data for initialization. This way, a stub can be used from different (test)-projects, each expecting a different result because the InitializeData is different. Very powerful! Now, the stub does not have to be programmed with different ifs to filter out different program-flows.

The last parameter, ServiceProvider, is the name of the ServiceProvider. This is not just to make each ServiceProvider unique. It can also be used to create the assembly. Creating the assembly can be on its interface or on the name you have given it in the config-file. This is done because there might be more classes with the same interface. So giving these a different name, you are able to load these as well.

The demo-application has the following config.xml file for its proceslayertest application:

<?xml version="1.0" encoding="utf-8" ?> <serviceproviders 
         xmlns= "urn://YourCompany.org/XMLSchema1.xsd">
   <serviceproviders>
   
      <serviceprovider interfacetype="Interfaces.IProcesLayer, Interfaces"
         type="ProcesLayer.Wallet, ProcesLayer">
         <name>Wallet</name>
      </serviceprovider>

      <serviceprovider initializedata="150" 
           interfacetype="Interfaces.IServiceLayer, Interfaces"
           type="ServiceLayer.ServiceStub, ServiceLayer.Stub">
         <name>ServiceStubLayer</name>
      </serviceprovider>

   </serviceproviders>
</serviceproviders>

The following config.xml file is for the 'production' application, the Windows application:

<?xml version="1.0" encoding="utf-8" ?>
   <serviceproviders 
     xmlns= "urn://YourCompany.org/XMLSchema1.xsd">
   <serviceproviders>
   
      <serviceprovider interfacetype="Interfaces.IProcesLayer, Interfaces"
         type="ProcesLayer.Wallet, ProcesLayer">
         <name>Wallet</name>
      </serviceprovider>

      <serviceprovider interfacetype="Interfaces.IServiceLayer, Interfaces"
         type="ServiceLayer.Service, ServiceLayer">
         <name>ServiceLayer</name>
      </serviceprovider>

   </serviceproviders>
</serviceproviders>

It should be clear from these two samples that only the service layer is switched. The same process layer is both called from the 'production' application and the ProceslayerTest application.

An array of ServiceProvider is embedded in ServiceProviders. Notice the internal namespace (= urn://YourCompany.org/XMLSchema1.xsd) being equal to the namespace in the config file. This namespace should be carefully chosen. Preferably, pick your company name.

In the test environment, the serviceLayer-serviceprovider has the type "ServiceLayer.ServiceStub, ServiceLayer.Stub". Whereas in the 'production' environment, this same provider has the type "ServiceLayer.Service, ServiceLayer". This is the switch I'm talking about. This can be redirected to another layer.

Points of Interest

Using a NMock-object could be another approach in testing layers in your application.

It is interesting to use an initialize data parameter in a production-environment. By setting the parameter, you can switch, for example, tracing on and off.

History

  • Version 1.0, 14 February 2006.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here