Search code examples
c#reflectionappdomain

How to invoke instance method from class library in different appdomain?


I know that there are many similar answers but none of them suit for me. I have a class library called MyLibrary. It has only one type. I'm going to create an instance of my type into another appdomain that why I don't use Activator.

public class Test
    {
        public Test()
        {
            Console.WriteLine("Ctor of Test type.");
        }

        public void Hello(string name)
        {
            Console.WriteLine($"Hello {name}! I'm an instance method.");
        }
    }

I created a simple console application. This is a code of Main method.

static void Main(string[] args)
        {
            string path = @"example of my path";
            AppDomain domain = AppDomain.CreateDomain("mydomain");
            Assembly mylibrary = Assembly.LoadFrom(path);
            Type typeOfTest = mylibrary.GetType("MyLibrary.Test");
            var instanceOfTest = domain.CreateInstanceFrom(path, typeOfTest.FullName);
            MethodInfo hello = typeOfTest.GetMethod("Hello");
            hello.Invoke(instanceOfTest, new object[] {"Bob"});
        }

What is the right way to call Hello method? I can create and call static method from Test type but I can do nothing with nonstatic instance method?


Solution

  • Read this article to get more information: How to load DLL in separate domain and use its methods?

    You should use the proxy class (Loader in this case). I changed a part of code from article above. Now the Call method takes your custom appdomain.

    public class Loader : MarshalByRefObject
        {
            object CallInternal(string dll, string typename, string method, object[] parameters)
            {
                Assembly a = Assembly.LoadFile(dll);
                object o = a.CreateInstance(typename);
                Type t = o.GetType();
                MethodInfo m = t.GetMethod(method);
                return m.Invoke(o, parameters);
            }
    
            public static object Call(AppDomain domain, string dll, string typename, string method, params object[] parameters)
            {
                Loader ld = (Loader)domain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(Loader).FullName);
                object result = ld.CallInternal(dll, typename, method, parameters);
                AppDomain.Unload(domain);
                return result;
            }
        }