How to use config files with .dll's (an idea - what do you think?)

  • Thread starter Thread starter Chris Finlayson
  • Start date Start date
C

Chris Finlayson

Hi:

There's quite a bit of interest out there in using config files with
..dll's. I've seen some implementations which boil down to figuring
out a file named "<something>.config.dll" and then using some manual
xml reader. I wanted to utilize the configSection of the app reader
whereby it defaults to the appropriate handlers as defined in the xml.
I did not want to rewrite that logic, so as an idea, I thought of
having a .dll redirect the call to another appdomain that's
dynamically created (so you can specify the configuration file).

With this approach, the .dll configuration loading is done in the same
way an app is loaded. I'd be curious to hear about what people think
of this approach. According to the documentation, creating appdomains
is pretty minimal overhead, both in speed and memory.

As a simple example, see the below three files:

1. the main program
2. MyDLL - a dll with a configuration file
3. MyDLL.config.dll - the config file to go with MyDLL, in a format
that adheres to the application configuration schema


/*************
The main program
****************/
using System;
using System.Reflection;
using System.Configuration;
using System.Security.Policy; //for evidence object
using System.Collections;
using System.Runtime.Remoting;

namespace App
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
AppDomain currentDomain = AppDomain.CurrentDomain;

//Create the application domain setup information.
AppDomainSetup domaininfo = new AppDomainSetup();
//I was just playing around with the below settings. Set up
AppDomainSetup
//however you see fit
domaininfo.ApplicationBase = currentDomain.BaseDirectory;
domaininfo.PrivateBinPath=currentDomain.BaseDirectory;
domaininfo.PrivateBinPathProbe=currentDomain.DynamicDirectory;

//Setting the config file is the most important
part. domaininfo.ConfigurationFile="C:\\junk\\ConfigTest\\App\\bin\\Debug\\MyDLL.dll.config";
//Create evidence for new appdomain.
Evidence adevidence = AppDomain.CurrentDomain.Evidence;
// Create the new application domain using setup information.
AppDomain domain = AppDomain.CreateDomain("MyDomain", adevidence,
domaininfo);


ObjectHandle o = domain.CreateInstance("MyDLL","MyDLL.Class1");
MyDLL.Class1 oclass1 = (MyDLL.Class1)o.Unwrap();
oclass1.SomeProperty();

Assembly[] assems = currentDomain.GetAssemblies();

//List the assemblies in the current application domain.
Console.WriteLine("List of assemblies loaded in current
appdomain:");
foreach (Assembly assem in assems)
Console.WriteLine(assem.ToString());



Console.WriteLine("\n\nList of assemblies loaded in other
appdomain:");
Assembly[] assems2 = domain.GetAssemblies();
foreach (Assembly assem in assems2)
Console.WriteLine(assem.ToString());

AppDomain.Unload(domain);
}
}
}

/***********
MyDLL .dll
*****************/
using System;
using System.Configuration;
using System.Collections;

namespace MyDLL
{
/// <summary>
/// Summary description for Class1.
/// </summary>
///


public class Class1 : MarshalByRefObject
{


public Class1()
{
//
// TODO: Add constructor logic here
//
}

public void Tester()
{
System.Console.WriteLine("testing...");
}

public bool SomeProperty()
{
IDictionary oHandler =
(IDictionary)System.Configuration.ConfigurationSettings.GetConfig("dictionarySample");
bool ret=oHandler.Contains("mykey");
if (ret)
{
System.Console.WriteLine("true!");
}

return ret;
}
}
}

----------the "MyDLL.config.dll" file-------------------
<configuration>
<configSections>
<section name="dictionarySample"
type="System.Configuration.DictionarySectionHandler"/>
</configSections>
<dictionarySample>
<add key="myKey" value="myValue"/>
</dictionarySample>
</configuration>
 
Chris said:
There's quite a bit of interest out there in using config files with
.dll's. I've seen some implementations which boil down to figuring
out a file named "<something>.config.dll" and then using some manual

Typo: <something>.dll.config

If it has the extension dll it is a dynamic link library!
xml reader. I wanted to utilize the configSection of the app reader
whereby it defaults to the appropriate handlers as defined in the xml.
I did not want to rewrite that logic, so as an idea, I thought of
having a .dll redirect the call to another appdomain that's
dynamically created (so you can specify the configuration file).

With this approach, the .dll configuration loading is done in the same
way an app is loaded. I'd be curious to hear about what people think
of this approach. According to the documentation, creating appdomains
is pretty minimal overhead, both in speed and memory.

Yes, this is a solution that has been suggested before but it is not ideal.
First, some comments about your code:
domaininfo.ConfigurationFile="C:\\junk\\ConfigTest\\App\\bin\\Debug\\MyDLL.d
ll.config";

Naughty! This will not be the same after you have used XCOPY deployment :-)
Use the BaseDirectory here.
ObjectHandle o = domain.CreateInstance("MyDLL","MyDLL.Class1");
MyDLL.Class1 oclass1 = (MyDLL.Class1)o.Unwrap();
oclass1.SomeProperty();

How useful do you think this is? You see, to access any type in the library
from the current domain you'll have to use .NET remoting to get across the
AppDomain boundary.

I guess the problem you are trying to solve is this: a library developer
wants to ship his library with a config file so that his code can read
settings from the file when the library types are used. The problem is that
by default the library reads from the app config file and hence the
library's config file must be merged by hand into the app's config file.

As it happens that is less of an effort than requiring the users of the
library to write special code to load the library into another app domain,
create types in the other app domain and then use .NET remoting to access
those objects.

Unfortunately .NET config files are not designed to allow you to have
separate files for libraries.

Richard
 
Thanks for the response (note the code is for testing purposes, so
that's why I have the hardcoded c:\\blahblahblah in there).

While manually merging into the app config file is ideal, this isn't
possible if one is extending a 3rd party application. For example,
assume Company X has some windows application that has an API allowing
one to customize it via .NET plugins. I'm Company Y extending company
X's app; I have no control over Company X's core application, and thus
no control over its config file. In this case, I don't see a way around
this besides this hack (or rewriting the app config loader logic).

--Chris.
 
Chris said:
While manually merging into the app config file is ideal, this isn't
possible if one is extending a 3rd party application. For example,
assume Company X has some windows application that has an API allowing
one to customize it via .NET plugins. I'm Company Y extending company
X's app; I have no control over Company X's core application, and thus
no control over its config file. In this case, I don't see a way
around this besides this hack (or rewriting the app config loader
logic).

Yes, you cannot have control over their config file. However, how does their
app know that they have to create your app in another app domain? If there
is some 'standard' (ie Company X says that this is the way that they load
your library) then surely they could come up with a mechanism to allow you
to merge stuff into their config file.

It seems to me that what you are suggesting is a poor use of the isolation
aspect of AppDomains (security and exception propagation and there are also
issues about attaching a debugger). Also it will unnecessarily get in the
way of accessing objects in the library. I agree that the design of config
files are deficient in this respect, but on balance its better either to
load your own config file explicitly (the XmlSerializer class is remarkedly
good in this respect) or use the apps config file. I prefer to read my own
config file because I can get over the section caching which I dislike
because it works against me in many cases.

Richard
 
Back
Top