Dynamically loading UserControl in WPF Assembly missing resources

59 Views Asked by At

I have a WPF application with a TabControl where the TabItems are loaded dynamically during runtime. It's not known which tabs will be loaded when the application starts. This is why I use the following code to add the .dll's to the Assembly:

// Load the UserControl to the Assembly
Assembly asm = Assembly.LoadFile(ProjectPath + "\\ControlLibrary.dll");

// Resolve the missing files from the loaded UserControl
AppDomain.CurrentDomain.AssemblyResolve += (obj, arg) =>
{
    // Get full name of missing dll
    var name = $"{new AssemblyName(arg.Name).Name}.dll";

    if (arg.RequestingAssembly != null && arg.RequestingAssembly.Location != null)
    {
        string tmp = Path.GetDirectoryName(arg.RequestingAssembly.Location);
        var referenceFiles = Directory.GetFiles(tmp, "*.dll", SearchOption.AllDirectories);

        // Attempt to find missing file in project directory
        var assemblyFile = referenceFiles.Where(x => x.EndsWith(name)).FirstOrDefault();
        // Load missing reference if found
        if (assemblyFile != null)
        {
            return Assembly.LoadFile(assemblyFile);
        }

    }
    throw new Exception($"'{name}' Not found");
};

This works just fine when I only load one tab.

The problem is that all the tabs are UserControls and all they are all called ControlLibrary.dll. The contents of these UserControls differ, so one instance may have custom controls that the other doesn't. When I load 2 tabs and switch between these tabs, I get IOExceptions telling me that some custom controls are not found. These controls only exist in one instance of the ControlLibrary.dll so my guess is that the resources are only loaded for the first instance of the ControlLibrary.

In the code sample above the only files that are being resolved are .dll files but the event handler is also called where the arg.Name contains ControlLibrary.resources. As this isn't a .dll file no further action is taken. There also isn't a file with the name ControlLibrary.resources in the output directory so I'm unsure how this has to be loaded.

I went down the MEF rabbithole to load the files but this eventually ended up in getting ChangeRejectedExceptions when I tried to load the second ControlLibrary.dll. For this I used the code below:

// Load the ControlLibrary assembly
var controlLibraryAssembly = Assembly.LoadFrom(assemblyPath);

// Create a catalog for the ControlLibrary assembly
var controlLibraryCatalog = new AssemblyCatalog(controlLibraryAssembly);

// Add the ControlLibrary catalog to the AggregateCatalog
((AggregateCatalog)container.Catalog).Catalogs.Add(controlLibraryCatalog);

// Compose the new parts
container.ComposeParts(this); // This throws a ChangeRejectionException.
0

There are 0 best solutions below