Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to load assemblies to the current app domain to the c# project dynamically?

I'm trying to load third party assemblies dynamically to the project and use reflection to create instance of their types.

I used:

Assembly.LoadFrom("Assembly1.dll")
Assembly.LoadFrom("Assembly2.dll")
Assembly.LoadFrom("Assembly3.dll") 

Also, tried:

AppDomain.CurrentDomain.Load("Assembly1.dll")
AppDomain.CurrentDomain.Load("Assembly2.dll")
AppDomain.CurrentDomain.Load("Assembly3.dll") 

However, I keep getting The method is not implemented exception while I try to create instance of one of their type as follow:

Assembly.LoadFrom("Assembly1.dll")
Assembly.LoadFrom("Assembly2.dll")
Assembly assembly=  Assembly.LoadFrom("Assembly3.dll")
Type type=assembly.GetType("Assembly3.Class1")
object instance=Activator.CreateInstance(type); //throws exception at this point

However, if I directly add reference to Assembly1, Assembly2 and Assembly3 in the project and do:

Assembly3.Class1 testClass=new Assembly3.Class1();

I get no exception

I just wanted to know what I'm doing wrong? How do I load assemblies to the project dynamically. I'm guessing since creation of Class1 instance depends on another assembly Assembly1 and Assembly2, so it's failing. So, how do I load all the dependent assemblies dynamically to the appdomain/loadcontext.

Greatly appreciate your answers.

like image 711
ANewGuyInTown Avatar asked Oct 31 '22 02:10

ANewGuyInTown


2 Answers

For resolve dependencies you need to handle AppDomain.AssemblyResolve Event

using System;
using System.Reflection;

class ExampleClass
{
    static void Main()
    {
        AppDomain ad = AppDomain.CurrentDomain;

        ad.AssemblyResolve += MyAssemblyResolveHandler;

        Assembly assembly = ad.Load("Assembly3.dll");

        Type type = assembly.GetType("Assembly3.Class1");

        try
        {
            object instance = Activator.CreateInstance(type);
        } 
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

    static Assembly MyAssemblyResolveHandler(object source, ResolveEventArgs e) 
    {
        // Assembly.LoadFrom("Assembly1.dll")
        // Assembly.LoadFrom("Assembly2.dll")

        return Assembly.Load(e.Name);
    }
}

The MyAssemblyResolveHandler triggered for each assembly than not loaded, including dependencies.

like image 66
ArcangelZith Avatar answered Nov 15 '22 03:11

ArcangelZith


When using "ad.AssemblyResolve += MyAssemblyResolveHandler", I got the infinite loop described by 'cdie'.

So I tried a couple of thing. The following was via the MSDNs LoadFrom link

public object InitClassFromExternalAssembly(string dllPath, string className)
{
    try
    {
        Assembly assembly = Assembly.LoadFrom(dllPath);
        Type type = assembly.GetType(className);
        var instance = Activator.CreateInstance(type);
        return instance;
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
        throw;
    }
}

Apparently, the Assembly.LoadFrom method requires the full path of the DLL.

Please note the possible problems loading an assembly via LoadFrom in the link.

Also, the link included by 'ArcangelZith' above has some interesting ideas.

like image 25
Jupiter Avatar answered Nov 15 '22 03:11

Jupiter