Problem with Dynamic loading of Assemblies

E

Ender

I have an application that I would like third party developers to be
able to create Plug-ins that will be dynamically loaded into our
application to extend functionality.

I have utilized the "Let Users Add Functionality to Your .NET
Applications with Macros and Plug-Ins" article at MSDN for the dynamic
loading of DLLs

http://msdn.microsoft.com/msdnmag/issues/03/10/Plug-Ins/default.aspx

We have an interface defined and everything was working fine. Users
would implement the interface and we would load the object dynamically
and our client application would properly implement the functionality.

I then went and create a Library class that would contain objects that
the third party developers need for utilization with their application
development. We have a reference to this Library class in our
Interface, and users need to implement properties that our part of the
library class. Upon adding this, and implementing the interface, our
dynamic loading of DLLs no longer functioned. I get a
ReflectionTypeLoadException error

"One or more of the types in the assembly unable to load."
System.SystemException: {"One or more of the types in the assembly
unable to load."}
_classes: {Length=2}
_exceptions: {Length=1}
LoaderExceptions: {Length=1}
Types: {Length=2}

and if I look at the LoaderExceptions the message I get is

{"Com.Corp.CorpImage.CorpImage"}
System.SystemException: {"Method get_CorpImageFields in type
Com.Corp.CorpImage.CorpImage from assembly CorpImage,
Version=1.0.1741.17159, Culture=neutral, PublicKeyToken=null does not
have an implementation."}
AssemblyName: "CorpImage, Version=1.0.1741.17159, Culture=neutral,
PublicKeyToken=null"
ClassName: "CorpImage"
Message: "Method get_CorpImageFields in type
Com.Corp.CorpImage.CorpImage from assembly CorpImage,
Version=1.0.1741.17159, Culture=neutral, PublicKeyToken=null does not
have an implementation."
MessageArg: "get_CorpImageFields"
ResourceId: 6012
TypeName: "Com.Corp.CorpImage.CorpImage"


I can get by the loading issue by skipping the loading of the Library
class when querying the types. While it's a work around, I am not
sure if it will enable everything to work down the road. I am also
unsure what I did :) Why does skipping trying to iterate the getTypes
of the Library dll enable things to work?

Again, the code is pretty similar to the one mentioned in the above
MSDN article. The change to the code I made to skip loading is as
follows...

private String[] DiscoverPluginAssembliesHelper(
String path, PluginCriteria criteria, Type criteriaType)
{
String[] assemblies;
// Get .dll names
path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, path);
assemblies = Directory.GetFiles(path, "*.dll");
try
{
if(assemblies.Length != 0)
{

ArrayList assembliesIncluded = new ArrayList();
foreach(String s in assemblies)
{
// Load the assembly (it it's not the control library)
if (s.ToLower().IndexOf("controllibrary") < 0)
{
Assembly assembly = Assembly.LoadFrom(s);
// Find matching type?
Type[] types = assembly.GetTypes();
foreach(Type t in types)
{
if(IncludeType(t, criteria, criteriaType))
{
assembliesIncluded.Add(s);
break; // match found, move on
}
}
}
}
// Get array of matching assemblies
assemblies = (String[])assembliesIncluded.ToArray(
typeof(String));
}
}
catch (ReflectionTypeLoadException oEx)
{
throw new Exception("Error discovering plugin assemblies",oEx);
}
catch (Exception oEx)
{
throw new Exception("Error discovering plugin assemblies",oEx);
}
return assemblies;
}

Any insights greatly appreciated

Endymion Keats
 
R

Richard Blewett [DevelopMentor]

Where is the interface assembly? The assembly resolver will only look in your APPBASE (normally the directory the application is running in) and a subdirectory with the same simple name as the assembly (unless the interface assembly has a strong name). So if your interface is in an assembly called iface.dll and your app is running from the C:\Foo directory, then the assembly resolver will only look in the directories

C:\foo
C:\foo\iface

unless you extend the seatch path via the <probing> element in the appliction config file.

I suspect that when enumerating the types it cannot find the interafce dll for one of the types when it loads the type information

Regards

Richard Blewett - DevelopMentor
http://staff.develop.com/richardb/weblog

nntp://news.microsoft.com/microsoft.public.dotnet.languages.csharp/<[email protected]>

I have an application that I would like third party developers to be
able to create Plug-ins that will be dynamically loaded into our
application to extend functionality.

I have utilized the "Let Users Add Functionality to Your .NET
Applications with Macros and Plug-Ins" article at MSDN for the dynamic
loading of DLLs

http://msdn.microsoft.com/msdnmag/issues/03/10/Plug-Ins/default.aspx

We have an interface defined and everything was working fine. Users
would implement the interface and we would load the object dynamically
and our client application would properly implement the functionality.

I then went and create a Library class that would contain objects that
the third party developers need for utilization with their application
development. We have a reference to this Library class in our
Interface, and users need to implement properties that our part of the
library class. Upon adding this, and implementing the interface, our
dynamic loading of DLLs no longer functioned. I get a
ReflectionTypeLoadException error
 
E

Endymion Keats

I tried putting the <Probing> tag into my App.config file and that did
not resolve the issue.

I am not very well versed in Assemblies and application domains. I
believe I am testing the assemblies that implement the interface in a
second domain, and then they get added to my executing application
domain. Could this be part of the issue?

Endymion Keats
 
R

Richard Blewett [DevelopMentor]

What makes you say you are running the code in a secondary AppDomain? Have you coded is this way by using AppDomain.CreateDomain() ?

Regards

Richard Blewett - DevelopMentor
http://staff.develop.com/richardb/weblog

nntp://news.microsoft.com/microsoft.public.dotnet.languages.csharp/<[email protected]>

I tried putting the <Probing> tag into my App.config file and that did
not resolve the issue.

I am not very well versed in Assemblies and application domains. I
believe I am testing the assemblies that implement the interface in a
second domain, and then they get added to my executing application
domain. Could this be part of the issue?

Endymion Keats



---
Incoming mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.771 / Virus Database: 518 - Release Date: 28/09/2004



[microsoft.public.dotnet.languages.csharp]
 
E

Endymion Keats

Yes, I am.

The MSDN exmaple code cited above, creates a temporary application
domain. The discovery of the DLLs that implement the interface then
uses this temporary application domain to identify DLLs that implement
the interface. My understanding is the reason this is done because once
you load the DLL into the domain, you can't unload without killing the
application domain, so by creating the second domain, you are able to
reduce your memory footprint.

However, I have tried using both the base application domain and a
temporary one and neither seems to work.

Thanks for the help

Endymion Keats
 
R

Richard Blewett [DevelopMentor]

We need to test whether my theory of the interface assembly not being loaded is correct. Cna you run up the fusion log viewer (fuslogvw.exe) and check the checkbox which states to log failures. Unfortunateely I can never remember the sequence to see the failed logs - I seem to remember its never as stiaghtforward as it should be. Run the app and let it fail, now see if fuslogvw shows any errors. If not, shut down fuslogvew and restart it - any errors now? If not re-reun the app and let it fail - any errors now? if not shut down and restart fuslogvw - any errors now? If we get to here and there are no errors then I think that its not a cas eof the interafce assembly failing to load.

If you do see an error can yoiu post the log entry so we can see what the asembly resolver tried to do

Regards

Richard Blewett - DevelopMentor
http://staff.develop.com/richardb/weblog

nntp://news.microsoft.com/microsoft.public.dotnet.languages.csharp/<[email protected]>


Yes, I am.

The MSDN exmaple code cited above, creates a temporary application
domain. The discovery of the DLLs that implement the interface then
uses this temporary application domain to identify DLLs that implement
the interface. My understanding is the reason this is done because once
you load the DLL into the domain, you can't unload without killing the
application domain, so by creating the second domain, you are able to
reduce your memory footprint.

However, I have tried using both the base application domain and a
temporary one and neither seems to work.

Thanks for the help

Endymion Keats




---
Incoming mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.771 / Virus Database: 518 - Release Date: 28/09/2004



[microsoft.public.dotnet.languages.csharp]
 
E

Endymion Keats

I have run the fuslogvw.exe a couple of times and have not seen any
errors.

If I comment out the property I have the implements the Control library
DLL in my interface, I am able to run the application fine, so I am
pretty sure the Interface is loading and executing properly. Once I try
and implement the Control library dll, things stop loaidng.

Endymion Keats
 
R

Richard Blewett [DevelopMentor]

I'm sorry, I don't know what you mean by "implement the control library"

Regards

Richard Blewett - DevelopMentor
http://staff.develop.com/richardb/weblog

nntp://news.microsoft.com/microsoft.public.dotnet.languages.csharp/<#[email protected]>


I have run the fuslogvw.exe a couple of times and have not seen any
errors.

If I comment out the property I have the implements the Control library
DLL in my interface, I am able to run the application fine, so I am
pretty sure the Interface is loading and executing properly. Once I try
and implement the Control library dll, things stop loaidng.

Endymion Keats




---
Incoming mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.771 / Virus Database: 518 - Release Date: 28/09/2004



[microsoft.public.dotnet.languages.csharp]
 
E

Endymion Keats

Sorry, for the confusion.

I have an Interface, iFoo. I then create a DLL that implements the
interface, clsFooDog. If I do this, everything works fine. I am able
to load the class clsFooDog and access it's methods and properties fine.

My problem comes in the next step I take. I develop a class library (I
call this the ControlLibrary) that has methods and properties that I
want the interface class to implement. So in iFoo, I put a reference
and an imports statement for the ControlLibrary class. I then put a
property in the iFoo interface that uses a collection class in the
ControlLibrary as the type.

Once I do this, I am unable to load clsFooDog.

Thanks Again

Endymion Keats
 
E

Endymion Keats

I have discovered the issue that was causing this problem.

In the ControlLibrary class, there was a bug in the constructor that was
causing it to error out.

This is what was causing the error message to be created, because the
type had trouble being instantiated.

Thanks for the help
 

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