Shannon Braun's Weblog
"Assembly Required"
« AppSettings Per Assembly Config Implemen...
Latest post
Contract First Web Service Development »
Basic Assembly Configuration
Sunday, November 14, 2004 12:00:00 AM (Central Standard Time, UTC-06:00)
Here is simple implementation that supports a configuration file for an assembly. I say simple because it only takes in account the configuration for the dll, it does not include the app, machine or other configs that make up the configuration of an application.
The AssemblyConfiguration class by default requires the dll that contains the AssemblyConfiguration and the dll that you want to support configuration are in the same directory. You can override the behavior by using the constructor that takes the path to the assembly and a reference to the assembly.
1
using
System;
2
using
System.Configuration;
3
using
System.Reflection;
4
using
System.Xml;
5
using
System.Windows.Forms;
6
7
8
using
TidByte.Activation;
9
10
11
namespace
TidByte.Configuration
12
{
13
///
<summary>
14
///
Supports the loading of a configuration file for a .dll
15
///
</summary>
16
public
class
AssemblyConfiguration
17
{
18
string
_cfgFile =
string
.Empty;
19
XmlDocument _doc =
null
;
20
string
_appPath =
string
.Empty;
21
22
///
<summary>
23
///
Default constructor that assumes that the the TidByte.Configuration dll is located in the same directory as the
24
///
.dll that requires the AssemblyConfiguration implementation. If you need to override this behavior, you will need to
25
///
use the constructor that supports the identification of a path of where the dll that required configuration is located.
26
///
</summary>
27
public
AssemblyConfiguration() :
this
(AppDomain.CurrentDomain.BaseDirectory, Assembly.GetCallingAssembly()) { }
28
29
///
<summary>
30
///
Supports identifying the path of the assembly that requires configuration. Defaults to the calling assembly as the assembly
31
///
that requires configuration.
32
///
</summary>
33
///
<param name="appPath">
Path to assembly to requires identification
</param>
34
public
AssemblyConfiguration(
string
appPath) :
this
(appPath, Assembly.GetCallingAssembly()) { }
35
36
///
<summary>
37
///
Supply the path, and assembly that requires configuration.
38
///
</summary>
39
///
<param name="appPath"></param>
40
///
<param name="asm"></param>
41
public
AssemblyConfiguration(
string
appPath, Assembly asm)
42
{
43
//set the dll config file name
44
_cfgFile = asm.CodeBase + ".config";
45
46
//load it into the DOM
47
_doc =
new
XmlDocument();
48
_doc.Load(
new
XmlTextReader(_cfgFile));
49
50
_appPath = appPath;
51
52
}
53
54
55
///
<summary>
56
///
Returns the configuration according to the configSection defined in the config file
57
///
</summary>
58
///
<param name="section">
Section of the config file that supports the configuration settings.
</param>
59
///
<returns></returns>
60
public
object
GetConfig(
string
section)
61
{
62
//gets the config section that is requested
63
XmlNode sectionNode = _doc["configuration"]["configSections"].SelectSingleNode("./section[@name='" + section + "']");
64
65
if
(sectionNode !=
null
)
66
{
67
//get the type of the object to create
68
string
typeDef = sectionNode.Attributes["type"].Value;
69
IConfigurationSectionHandler cfgHandler = (IConfigurationSectionHandler)ActivationHelper.ActivateFromPath(typeDef, _appPath);
70
71
XmlNode sectionXml = _doc["configuration"].SelectSingleNode("./" + section);
72
73
//Call the interface
74
return
cfgHandler.Create(sectionNode.ParentNode,
null
,sectionXml);
75
76
}
77
78
return
null
;
79
}
80
81
}
82
}
The next code snippet shows the implementation for how the ActivationHelper works:
1
using
System;
2
using
System.Reflection;
3
using
System.Windows.Forms;
4
5
namespace
TidByte.Activation
6
{
7
///
<summary>
8
///
Summary description for ActivationHelper.
9
///
</summary>
10
public
class
ActivationHelper
11
{
12
const
int
AssemblyName = 1;
13
const
int
ClassName = 0;
14
15
//default constructor
16
public
ActivationHelper() {}
17
18
///
<summary>
19
///
Private helper function to assist in run-time activations. Returns
20
///
an object from the specified assembly and type.
21
///
</summary>
22
///
<param name="assembly">
Name of the assembly file (w/out extension)
</param>
23
///
<param name="typeName">
Name of the type to create (namespace must be included)
</param>
24
///
<returns>
Instance of the type specified in the input parameters.
</returns>
25
public
static
object
Activate(
string
assembly,
string
typeName)
26
{
27
try
28
{
29
30
return
AppDomain.CurrentDomain.CreateInstanceAndUnwrap(assembly, typeName);
31
}
32
catch
( Exception ex)
33
{
34
throw
ex;
35
}
36
}
37
38
///
<summary>
39
///
Private helper function to assist in run-time activations. Returns
40
///
an object from the specified assembly and type, as defined in a standard config
41
///
</summary>
42
///
<param name="arArgs">
namespace.class (comma seperated),assembly filename
</param>
43
///
<returns>
Instance of the type specified in the input parameters.
</returns>
44
public
static
object
Activate(
string
assm)
45
{
46
47
string
[] arArgs = assm.Split(
new
char
[]{','});
48
string
assmname = arArgs[AssemblyName].Trim();
49
string
clsname = arArgs[ClassName].Trim();
50
51
52
//Dynamically load the deployment handler from the config file
53
return
Activate(assmname, clsname);
54
55
}
56
57
///
<summary>
58
///
Activate a specific assembly from a specified path
59
///
</summary>
60
///
<param name="assm"></param>
61
///
<param name="path"></param>
62
///
<returns></returns>
63
public
static
object
ActivateFromPath(
string
assm,
string
path)
64
{
65
66
67
string
[] arArgs = assm.Split(
new
char
[]{','});
68
string
assmname = arArgs[AssemblyName].Trim();
69
string
clsname = arArgs[ClassName].Trim();
70
71
Assembly lib = Assembly.LoadFrom(path + assmname + ".dll");
72
73
return
lib.CreateInstance(clsname);
74
}
75
}
76
}
And last I am using a modified version of Craig Andreas "
The last configuration handler I'll ever need
".
1
using
System;
2
using
System.Reflection;
3
using
System.IO;
4
using
System.Configuration;
5
using
System.Xml;
6
using
System.Xml.Serialization;
7
using
System.Xml.XPath;
8
using
System.Windows.Forms;
9
10
11
using
TidByte.Activation;
12
13
namespace
TidByte.Configuration
14
{
15
16
/*
17
* When you map a section of your configuration file to this handler, using an entry in your config file that looks like this:
18
19
<configuration>
20
<configSections>
21
<section name="MyStuff" type="<Namespace>.XmlSerializerSectionHandler, Exe/DllName"/>
22
</configSections>
23
</configuration>
24
25
What happens is that any time you ask for the MyStuff section of the config file with code that looks like this:
26
AppConfig.GetTypeSafeConfig("MyStuff");
27
28
It will actually go look in the config file to figure out who knows how to deal with the “MyStuff” section.
29
When it sees that it’s the XmlSerializerSectionHandler, it’ll create an instance of this object and call Create,
30
passing it (via the section parameter) a reference to the relevant portion of the config file. In our case, it might look something like this:
31
<configuration>
32
<!-- configSections element goes here -->
33
<MyStuff type="SomeNamespace.MyStuff, CraigsConfig">
34
<Foo>1.234</Foo>
35
<Bar>A bunch of information</Bar>
36
</MyStuff>
37
</configuration>
38
39
What my handler does is to look for the “type” attribute on this bit of XML, in the form “classname, assemblyname”.
40
In this case, it’s a class called MyStuff in a namespace SomeNamespace. It then – and here’s the good bit –
41
uses the XmlSerializer to initialize an instance of this type from the XML in the configuration file.
42
The XmlSerializer is a very cool piece of the .NET libraries, and you should check it out if you haven’t already.
43
Basically, you write a type like this:
44
45
public class MyStuff
46
{
47
private float foo;
48
private string bar;
49
50
public float Foo
51
{
52
get { return foo; }
53
set { foo = value; }
54
}
55
56
public string Bar
57
{
58
get { return bar; }
59
set { bar = value;
60
}
61
}
62
63
And the XmlSerializer takes care of turning it into the XML above and vice versa. There are even a bunch of
64
attributes you can use to control the process.
65
66
[XmlRoot("RootElemenet")] - allows the naming of a root element
67
[XmlElement("FileName")] - overrides a property name
68
[XmlAttribute("FileName")] - stores a property as an attribute
69
[XmlArray("CollectionName")] - assigns a collection a name
70
[XmlArrayItem("CollectionChildName")] - assigns the children of the collection a name
71
72
Calling:
73
74
MyStuff ms = (MyStuff) AppConfigEx.GetTypeSafeConfig("MyStuff");
75
*/
76
77
public
class
XmlSerializerSectionHandler : IConfigurationSectionHandler
78
{
79
public
object
Create(
80
object
parent,
81
object
configContext,
82
System.Xml.XmlNode section)
83
{
84
try
85
{
86
//get the type that we need to create to support the configuration
87
XPathNavigator nav = section.CreateNavigator();
88
string
typename = (
string
) nav.Evaluate("string(@type)");
89
90
//Get the location of this dll. We assume that all dll's loaded through the config are installed to a private
91
FileInfo fi =
new
FileInfo(Assembly.GetExecutingAssembly().Location);
92
Type t = ActivationHelper.ActivateFromPath(typename, fi.DirectoryName + @"\").GetType();
93
XmlSerializer ser =
new
XmlSerializer(t);
94
95
96
//xpath will select all nodes below the parent and use those to create the type;
97
return
ser.Deserialize(
new
XmlNodeReader(section.SelectSingleNode("*")));
98
99
}
100
catch
(Exception ex)
101
{
102
Console.WriteLine(ex.ToString());
103
throw
ex;
104
}
105
}
106
107
}
108
109
}
Posted in
Code
|
Comments [0]
Comments are closed.
Archives
October, 2008 (11)
September, 2008 (5)
August, 2008 (1)
April, 2008 (4)
March, 2008 (4)
February, 2008 (1)
January, 2008 (3)
December, 2007 (2)
October, 2007 (1)
September, 2007 (1)
June, 2007 (5)
May, 2007 (1)
April, 2007 (1)
March, 2007 (7)
February, 2007 (4)
January, 2007 (2)
December, 2006 (1)
November, 2006 (7)
October, 2006 (7)
September, 2006 (5)
August, 2006 (5)
July, 2006 (1)
June, 2006 (2)
May, 2006 (4)
April, 2006 (2)
March, 2006 (1)
February, 2006 (4)
January, 2006 (6)
December, 2005 (2)
June, 2005 (2)
May, 2005 (6)
April, 2005 (1)
March, 2005 (2)
February, 2005 (1)
January, 2005 (2)
December, 2004 (1)
November, 2004 (4)
October, 2004 (6)
July, 2004 (1)
May, 2004 (2)
April, 2004 (4)
March, 2004 (6)
February, 2004 (2)
January, 2004 (5)
December, 2003 (10)
November, 2003 (9)
October, 2003 (12)
January, 2003 (2)
Category Cloud
Architecture and Design (9)
Code (24)
Development (35)
PDC 2008 (4)
Presentations (13)
TidByte (40)
Visual Studio .NET (12)
WPF (22)
Blogroll
David Ing
David Chappell
Harry Pierson
Rockey Lhotka
Scott Hanselman
Links
Home
MSDN
Microsoft Architecture Center
The MS Architect Journal
.NET Windows Forms
Asp.NET
Windows Communication Foundation
Microsoft Patterns/Practices
About
Sysknowlogy
Sign In