4

In C# there is ResolveEventHandler event to load external dll s if they are not inside application directory.

To use it in winform application I register the event in Program.cs Main() function like the following:

AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(ResolveAssembly);

and then there is the ResolveAssembly function that gets called every time the event is fired:

    static Assembly ResolveAssembly(object sender, ResolveEventArgs args)
    {
        //MessageBox.Show(String.Format("Assembly {0} is missing", args.Name));


        //This handler is called only when the common language runtime tries to bind to the assembly and fails.

        //Retrieve the list of referenced assemblies in an array of AssemblyName.
        Assembly MyAssembly, objExecutingAssemblies;
        string strTempAssmbPath = "";
        string AssemblyName = new AssemblyName(args.Name).Name;

        objExecutingAssemblies = Assembly.GetExecutingAssembly();
        AssemblyName[] arrReferencedAssmbNames = objExecutingAssemblies.GetReferencedAssemblies();

        //Loop through the array of referenced assembly names.
        foreach (AssemblyName strAssmbName in arrReferencedAssmbNames)
        {
            //Check for the assembly names that have raised the "AssemblyResolve" event.
            if (strAssmbName.Name == AssemblyName)
            {
                //Build the path of the assembly from where it has to be loaded.                
                strTempAssmbPath = @"C:\PowerVision\libraries\" + AssemblyName + ".dll";
                break;
            }

        }
        //Load the assembly from the specified path.                    
        MyAssembly = Assembly.LoadFrom(strTempAssmbPath);

        //Return the loaded assembly.
        return MyAssembly;
    }

The question is how can I add/call this event in/from class library?

I have a class library (DLL) that has 3 references to external DLL s. I don't want to copy these dlls into application directory and don't want to place them into application's subdirectory. These DLLs should stay in a specific external folder (hence using the event).

The problem is I don't know where in DLL(class library) to put this event registration:

AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(ResolveAssembly);
John Saunders
  • 160,644
  • 26
  • 247
  • 397
  • I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackexchange.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders Jan 31 '13 at 13:22
  • Thank you very much and I'm sorry :) – Alexander Benjamin Jan 31 '13 at 13:28
  • @AlexanderBenjamin This got me well on the way to resolving assemblies, question though, why in your code for you foreach over reference assemblies, and potentially return an empty string if the assembly does not reference? I.e. .resources? Finally how do you handle situations where your assembly is not listed in references assemblies but actually is? – Gregory William Bryant Aug 10 '20 at 16:05

1 Answers1

1

You just need to put the event registration in your DLL in a place that gets called sometime BEFORE any of your 3 external DLLs get referenced.

A constructor of an object in your top DLL would be the first place to look. However, if that object is a sub-type of an object that is in one of those 3 external DLLs, then you may need to create a parent object for that object, and call the parent object first, and add the event registration in that parent's constructor.

E.g. if your DLL is a UserControl that is based on another UserControl that is in one of those 3 external DLL's, like this:

public partial class TopLevelUserControl: ExternalDllUserControl
{
    InitializeComponent();
}

then you may need to write code like this: Create a new user control called TopLevelUserControlLauncher, and place TopLevelUserControl in that userControl, docked. Then write code like this:

public partial class TopLevelUserControlLauncher: UserControl
{
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(ResolveAssembly);
    InitializeComponent(); // this will construct TopLevelUserControl
}
philu
  • 795
  • 1
  • 8
  • 17