Dynamically Loaded Assemblies and Custom ConfigurationSection Handlers

S

Smithers

I have a Windows Forms application that implements a plug-in architecture
whereby required assemblies are identified and loaded dynamically.

Here are the relevant classes:

A = application = Windows Forms class

B = a singleton hosted within A. B is responsible for dynamically loading
classes X, Y, and Z.

X, Y, and Z = "worker bee" classes that do all of the grunt work of this
application. Each of these classes exists in its own assembly. B loads their
containing assemblies dynamically via reflection:
System.Reflection.Assembly.LoadFile(pathToAssembly).

Being that X, Y, and Z are contained within their respective class
libraries, they cannot have their own .config files. I decided it was okay,
for this particular application, for the App.config file (of A, the
application class) to have custom configuration sections for each of the X,
Y, and Z classes. So X, Y, and Z, if/when loaded, need to read their
respective custom configuration sections from App.config.

Now, to get into the problem area:
I am dynamically loading the assemblies containing X, Y, and Z from
C:\SomeFolder --- and NOT from \bin or a subfolder under \bin

The loading of the assemblies happens just fine, as I am able to specify the
full path to the assemblies via Assembly.LoadFile(pathToAssembly).

So far so good.

Here's where the problem happens:

While X, Y, and Z can read App.config - no problem - the custom
ConfigurationSection handler classes, which are also compiled into the
assemblies containing classes X, Y, and Z are INCORRECTLY assumed by the CLR
to exist in assemblies located in or under project A's \bin. I have verified
this through my testing:

Test 1:
If I ensure that the assemblies for X, Y, and Z do NOT exist in project A's
\bin, then I get this exception message when the custom ConfigurationSection
handler classes are attempted to be instantiated:
"An error occurred creating the configuration section handler for
NameOfCustomConfigurationSectionHandler: Could not load file or assembly
'MyCompany.AssemblyX' or one of its dependencies. The system cannot find the
file specified."

Test 2:
I then place a copy of the assembly containing X, Y, or Z into \bin\Debug.
Note that at this point TWO copies of, assembly X (for example), are in
play - one in C:\SomeFolder, and another in project A's \bin\Debug. Here's
the ensuing exception message:
"Unable to cast object of type 'MyCompany.MyNamespace.XSettings' to type
'MyCompany.MyNamespace.XSettings'."

"XSettings" is the name of my custom ConfigurationSection class (real names
changed to protect the innocent).
Notice that this message is telling us that it cannot cast to and from the
EXACT SAME type. This suggests to me that the CLR believes these are
different types [even though the qualified names are identical] BECAUSE they
are loaded from different assemblies - the first being the copy of the
assembly loaded via reflection from C:\SomeFolder and the other assembly
loaded by the .NET Configuration system from project A's \bin\Debug folder.

Attempted Resolution:
In trying to resolve this I started with a look at how the custom
configuration section handler is/can be defined in App.config:
<configSections>
<section name="MySection"
type="MyCompany.MyNamespace.ClassName, MyCompany.AssemblyX" />
..
What's going on here is the type attribute lets us specify the qualified
class name, a comma, and finally the name of the assembly in which the class
can be found (less the .dll extension of course).

In reading MSDN and points beyond, it appears that we cannot specify a path
to the assembly file here - only the assembly name. The CLR apparently then
attempts to locate the assembly in or under \bin

I then attempted to introduce the <probing> element into App.config to tell
the CLR where to look if it could not find the assemblies in or under \bin:
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="bin;c:\SomeFolder"/>
</assemblyBinding>
</runtime>

NO dice with that per my testing, plus the docs say that <probing> can ONLY
be used to specify folders under \bin

So I'm fresh out of ideas on how to resolve this. I would appreciate
suggestions for how to make this work. Is there any way to tell the CLR to
load custom configuration section handlers from assemblies that exist
somewhere other than in or under \bin ??? That would be great. If not, I'd
appreciate suggestions for making this work that don't entail me introducing
a bunch of dependencies or breaking out the custom configuration section
handlers into their own\separate assemblies; or otherwise breaking my slick
plug-in architecture. It's taken a bunch of work to get X, Y, and Z to
participate in the application with A knowing absolutely nothing and B
knowing practically nothing about them (and vice versa); I'd like to keep it
like that if possible.

FWIW: This whole thing has been developed from scratch using Visual Studio
2008 Beta 2 (.NET 3.5). and no problems with Beta 2 - totally stable for me
with full-time development since a day or two after it was released.

Thanks!
 
G

Guest

Can you pls ask the question more briefly?
--
Sincerely
Yaron Karni
http://dotnetbible.blogspot.com/


Smithers said:
I have a Windows Forms application that implements a plug-in architecture
whereby required assemblies are identified and loaded dynamically.

Here are the relevant classes:

A = application = Windows Forms class

B = a singleton hosted within A. B is responsible for dynamically loading
classes X, Y, and Z.

X, Y, and Z = "worker bee" classes that do all of the grunt work of this
application. Each of these classes exists in its own assembly. B loads their
containing assemblies dynamically via reflection:
System.Reflection.Assembly.LoadFile(pathToAssembly).

Being that X, Y, and Z are contained within their respective class
libraries, they cannot have their own .config files. I decided it was okay,
for this particular application, for the App.config file (of A, the
application class) to have custom configuration sections for each of the X,
Y, and Z classes. So X, Y, and Z, if/when loaded, need to read their
respective custom configuration sections from App.config.

Now, to get into the problem area:
I am dynamically loading the assemblies containing X, Y, and Z from
C:\SomeFolder --- and NOT from \bin or a subfolder under \bin

The loading of the assemblies happens just fine, as I am able to specify the
full path to the assemblies via Assembly.LoadFile(pathToAssembly).

So far so good.

Here's where the problem happens:

While X, Y, and Z can read App.config - no problem - the custom
ConfigurationSection handler classes, which are also compiled into the
assemblies containing classes X, Y, and Z are INCORRECTLY assumed by the CLR
to exist in assemblies located in or under project A's \bin. I have verified
this through my testing:

Test 1:
If I ensure that the assemblies for X, Y, and Z do NOT exist in project A's
\bin, then I get this exception message when the custom ConfigurationSection
handler classes are attempted to be instantiated:
"An error occurred creating the configuration section handler for
NameOfCustomConfigurationSectionHandler: Could not load file or assembly
'MyCompany.AssemblyX' or one of its dependencies. The system cannot find the
file specified."

Test 2:
I then place a copy of the assembly containing X, Y, or Z into \bin\Debug.
Note that at this point TWO copies of, assembly X (for example), are in
play - one in C:\SomeFolder, and another in project A's \bin\Debug. Here's
the ensuing exception message:
"Unable to cast object of type 'MyCompany.MyNamespace.XSettings' to type
'MyCompany.MyNamespace.XSettings'."

"XSettings" is the name of my custom ConfigurationSection class (real names
changed to protect the innocent).
Notice that this message is telling us that it cannot cast to and from the
EXACT SAME type. This suggests to me that the CLR believes these are
different types [even though the qualified names are identical] BECAUSE they
are loaded from different assemblies - the first being the copy of the
assembly loaded via reflection from C:\SomeFolder and the other assembly
loaded by the .NET Configuration system from project A's \bin\Debug folder.

Attempted Resolution:
In trying to resolve this I started with a look at how the custom
configuration section handler is/can be defined in App.config:
<configSections>
<section name="MySection"
type="MyCompany.MyNamespace.ClassName, MyCompany.AssemblyX" />
..
What's going on here is the type attribute lets us specify the qualified
class name, a comma, and finally the name of the assembly in which the class
can be found (less the .dll extension of course).

In reading MSDN and points beyond, it appears that we cannot specify a path
to the assembly file here - only the assembly name. The CLR apparently then
attempts to locate the assembly in or under \bin

I then attempted to introduce the <probing> element into App.config to tell
the CLR where to look if it could not find the assemblies in or under \bin:
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="bin;c:\SomeFolder"/>
</assemblyBinding>
</runtime>

NO dice with that per my testing, plus the docs say that <probing> can ONLY
be used to specify folders under \bin

So I'm fresh out of ideas on how to resolve this. I would appreciate
suggestions for how to make this work. Is there any way to tell the CLR to
load custom configuration section handlers from assemblies that exist
somewhere other than in or under \bin ??? That would be great. If not, I'd
appreciate suggestions for making this work that don't entail me introducing
a bunch of dependencies or breaking out the custom configuration section
handlers into their own\separate assemblies; or otherwise breaking my slick
plug-in architecture. It's taken a bunch of work to get X, Y, and Z to
participate in the application with A knowing absolutely nothing and B
knowing practically nothing about them (and vice versa); I'd like to keep it
like that if possible.

FWIW: This whole thing has been developed from scratch using Visual Studio
2008 Beta 2 (.NET 3.5). and no problems with Beta 2 - totally stable for me
with full-time development since a day or two after it was released.

Thanks!
 
S

Smithers

Can you pls ask the question more briefly?

Sure.

Is there any way to tell the CLR to load custom configuration section
handlers from assemblies that exist somewhere other than in or under \bin
???

If the answer to the above question is "no" then...

I'd appreciate suggestions for making this work that don't entail me
introducing a bunch of dependencies or breaking out the custom configuration
section handlers into their own\separate assemblies; or otherwise breaking
my slick plug-in architecture (described in the OP).

Thanks

-S
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top