Could not load file or assembly

Topics: Prism v4 - WPF 4
Apr 24, 2012 at 10:26 PM

Hi,

We have a shell in path ".\xyz\shell\" which uses directorycatalog to load 2 different independent modules A and module B. These 2 modules do not have any inter dependencies.

Module A project has references to other assemblies(these are not module). Module A and its referenced assemblies are copied to path ".\comp1\moduleA\" in post build step.

Module B project has references to a different set of assemblies (this is not a module). Module B and all of its referenced assemblies are copied to path ".\comp2\Reporting\" in post build step.

When i run the application, it throws exception that the module referenced assemblies could not be loaded ("Could not load file or assembly ......"). If i copy the all of its referenced assemblies to the shell path, then it works, but i do not want module referenced assemblies to be side by the shell app. If i remove the referenences from both the modules, then the modules are loaded as expected. I  want modules and its referenced assemblies to be in its own path and shell be able to load the modules.

Has any body encountered this issue?

Would appreciate any help.

Thanks.

Developer
Apr 25, 2012 at 7:44 PM

Hi,

Based on my understanding when using the "Discovering modules in a directory" approach, you should not require the dependent dlls of the modules to be in the same directory as your shell application.

For example, I tried to reproduce the scenario you mentioned using the ModularityWithMef Quickstart as a starting point. Then I added a reference to a custom library to each of the modules discovered by inspecting a directory (Module B and Module D). Also I override the ConfigureAggregateCatalog method to register the directories like in the following code snippet:

   protected override void ConfigureAggregateCatalog()
        {
            base.ConfigureAggregateCatalog();
(...)
            DirectoryCatalog catalog1 = new DirectoryCatalog("D:\\ModuleB");

            DirectoryCatalog catalog2 = new DirectoryCatalog("D:\\ModuleD");

            this.AggregateCatalog.Catalogs.Add(catalog1);

            this.AggregateCatalog.Catalogs.Add(catalog2);
(...) 
    }

Note that I placed each module in a different directory, in my case I used absolute paths but this can also be done using relative paths.

After rebuilding the solution, I ensure that each module folder also contained the corresponding referenced assemblies for each module.

This way I could run the application without having the module dependent dlls in the shell application directory.

Perhaps in your case one of those dlls is also being referenced by your shell project.

Please let us know if we have misunderstood your scenario,

Regards,

Agustin Adami
http://blogs.southworks.net/aadami

Apr 27, 2012 at 10:53 PM

Hi Agustin,

Your understanding of my earlier post is right and Shell project does not references those dlls. Only module project references those dll.

On further investigation, here is my findings.

Little bit of background to the issue: Modules are loaded using DirectoryModuleCatalog. One of the views in my module project uses user control that is present in the referenced assembly (whose copy local = true).

If i place this user control in xaml file, then it fails to load and gives error  "could not load file or assembly xxxxxxxxxxx or one of its dependencies.....", but if i programatically create same user control in code behind/*.cs file and add to the some control say stack panel, then it works and this user control from referenced assemblie shows up in the view defined in the module project.

I was able to consistantly reproduce this behaviour with small demo app as well.

Hope this gives you more insight to the issue that i have.

Any suggestions are well appreciated.

Thanks in advance.

 

Developer
May 2, 2012 at 5:12 PM

Hi,

It would be helpful to know which dependency injection container you are using in your scenario (MEF or Unity). As for the case of MEF when discovering modules from a directory, you should use the DirectoryCatalog as mentioned in this section of the Prism documentation. On the other hand for Unity the DirectoryModuleCatalog should be used instead.

Also, if you already reproduced this behavior in a small demo, it would be helpful if you could upload it to SkyDrive or any other storage site you'd like to, and post the link here.

Regards,

Agustin Adami
http://blogs.southworks.net/aadami

May 10, 2012 at 9:32 PM

Hi Agustin,

I am using Unity for DI and using DirectoryModuleCatalog.

Have uploaded zip file here https://skydrive.live.com/redir.aspx?cid=a61b89d393645bc2&resid=A61B89D393645BC2!119&parid=A61B89D393645BC2!114&authkey=!AJV0bBDy6pjYrQk

Plugin1 has a reference to WPFToolkit.Extended with copylocal = true. When using BusyIndicator user control from WPFToolkit.Extended library in xaml code, gives me could not load file or assembly error, but if i create same usercontrol in xaml code behind, then every thing works fine. Try the code as it is and it should work. Comment the code in UserControl1.xaml.cs and uncomment the xaml code in UserControl1.xaml file and run to see the error. I can reproduce this with any other control whose library (dlls) is present only in the directory path where module exist and is not available in other path.

Hope this sample is clear and you are able to reproduce the issue.

Thanks

Developer
May 11, 2012 at 6:18 PM
Edited May 11, 2012 at 6:19 PM

Hi,

Thanks for taking the time to provide this sample. After checking this behavior we realize that the cause is not related to the way your module is loaded.
It seems that when only defining and using an assembly in XAML, this assembly won't be loaded if it's not present in the main applications folder. In fact this is not related to Prism as it can be reproduced in a simple WPF application.

On the other hand when using assemblies in your project files (like in the code behind as you mentioned) the assemblies are correctly loaded.

Another possible approach to avoid this, could be ensuring that the assembly is loaded before your view is resolved. For example, I manually loaded the assembly when the module initializes, like in the following code snippet:

 

public void Initialize()
{

//relative path to the main application
Assembly.LoadFrom(@".\Plugin1\WPFToolkit.Extended.dll");

(...)

}

However you should consider if adding this complexity is necessary instead of placing these dll files in you main project or simple adding a reference to them.

 

Regards,

Agustin Adami
http://blogs.southworks.net/aadami

May 11, 2012 at 9:04 PM

That answers. Was not aware it is an inherent problem with WPF.

Thanks for your response.

Shankaar