C # загрузите dll в appdomain вызовите методы без загрузки dll снова - PullRequest
0 голосов
/ 05 марта 2019

У меня есть consoleapp, загружающий одну dll в новый домен приложения, и я могу вызвать метод в этой dll.Я хотел бы иметь возможность вызвать этот метод снова без перезагрузки DLL.Предпочтительно я хотел бы иметь возможность загружать несколько dll и вызывать метод из любого из них перед выгрузкой домена приложения.

using System;

using System.Reflection;

namespace Parent
{
    public interface ILoader
    {
        int Execute(int arg1, int arg2);
    }

    public class Loader : MarshalByRefObject, ILoader
    {

        public int Execute(int arg1, int arg2)
        {

            byte[] test1 = System.IO.File.ReadAllBytes("C:\\Users\\username\\source\\repos\\Test\\Test\\bin\\Debug\\Test.dll");

            Assembly test = Assembly.Load(test1);
            foreach (Type type in test.GetTypes())
            {
                if (type.ToString().ToUpper() == "PROGRAM")
                {

                    var o = Activator.CreateInstance(type);
                    Console.WriteLine("found Program");
                    MethodInfo method = type.GetMethod("math", new[] { typeof(int), typeof(int) });
                    var returnvalue = method.Invoke(o, new object[] { arg1, arg2 });


                    return (int)returnvalue;
                }
                return 0;
            }
            return 0;
        }

    }
    class Program
    {
            static void Main(string[] args)
            {
                int arg1 = Convert.ToInt32(args[0]);
                int arg2 = Convert.ToInt32(args[1]);
                Console.WriteLine(args[0], args[1]);
                var domain = AppDomain.CreateDomain("child");
                var loader = (ILoader)domain.CreateInstanceAndUnwrap(typeof(Loader).Assembly.FullName, typeof(Loader).FullName);
                Console.Out.WriteLine(loader.Execute(arg1, arg2));
            //reloads appdomain I dont want that
            Console.Out.WriteLine(loader.Execute(2, 3));
                Console.ReadKey();
                AppDomain.Unload(domain);
                Console.WriteLine("Appdomain unloaded");
                Console.ReadKey();

            }
        }
    }

Тестовая DLL,

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


    class Program
    {
        public static int math(int arg1, int arg2)
        {
            int a = arg1;
            int b = arg2;
            int c = a + b;
            return c;
        }
    }

Ответы [ 2 ]

0 голосов
/ 07 марта 2019

Разобрался.Пришлось создать вторую функцию для загрузки двоичного файла и операторов if, если он еще не существует.Для тех, кто смотрит на домены приложений. Насколько я понимаю, интерфейс - это общие функции, которые позволяют вам вызывать класс, загруженный в другой домен приложения.

using Parent;
using System;
using System.Reflection;

namespace Parent
{
    public interface ILoader
    {

        int ExecuteAssm(int arg1, int arg2);
        byte[] Test();
    }

    public class Loader : MarshalByRefObject, ILoader
    {
        Assembly test1 = null;
        byte[] test;
        public byte[] Test()
        {
            byte[] test = System.IO.File.ReadAllBytes("C:\\Users\\username\\source\\repos\\Test\\Test\\bin\\Debug\\Test.dll");
            return test;
        }
        public int ExecuteAssm(int arg1, int arg2)
        {

            if (test1 == null)
            {
                test = Test();
                test1 = Assembly.Load(test);
            }

            foreach (Type type in test1.GetTypes())

                if (type.ToString().ToUpper() == "PROGRAM")
                {
                    MethodInfo method = type.GetMethod("math");
                    object o = test1.CreateInstance("math");
                    var returnint = method.Invoke(o, new object[] { arg1, arg2 });
                    Console.WriteLine(method);
                    Console.WriteLine(returnint);
                    return (int)returnint;
                }
            return 0;
        }
    }
        //Type t = test1.GetType("Test.Class1");

        //var methodInfo = t.GetMethod("math", new Type[] { typeof(int), typeof(int) });
        //var o = Activator.CreateInstance(t);
        //var result = MethodInfo.(o, new Type[] { 32, 32 });


    }

class Program
{
    static void Main(string[] args)
    {

        var domain = AppDomain.CreateDomain("child");
        var loader = (ILoader)domain.CreateInstanceAndUnwrap(typeof(Loader).Assembly.FullName, typeof(Loader).FullName);
        loader.ExecuteAssm(32, 32);
        loader.ExecuteAssm(2, 2);
        AppDomain.Unload(domain);
        // int returnint = ILoader.ExecuteAssm(32, 32);
        //Console.WriteLine(returnint);
    }
}
0 голосов
/ 05 марта 2019

Объявите вашу domain переменную как static переменную вне функции main, так как вы не можете объявить static переменные внутри функций.Переменная static не стирает свои данные после выполнения функций - поэтому она называется «статической», поскольку она никогда не изменяется, во многом как константа и в отличие от «динамической» переменной.

...