Как вызвать произвольный метод из другого AppDomain - PullRequest
0 голосов
/ 20 июня 2019

Я делаю менеджер плагинов, который взаимодействует со сторонним кодом. Я хотел бы, чтобы плагины перезагружались во время выполнения, а также получали доступ к стороннему коду (в домене приложений по умолчанию) из плагинов.

Я пытался использовать AppDomains, но я не нашел способа вызвать любой метод без необходимости оборачивать каждый доступный метод / объект.

Я рассмотрел пару вопросов, и, например, этот ответ , ссылки в нем и этот ответ дали некоторое представление о том, как работает связь между доменами AppDomain.

Я успешно создал прокси-класс для одного метода, который будет вызываться в домене приложений по умолчанию благодаря второму ответу, но для этого потребуется добавить один для каждого возможного вызова метода, который будет вызываться из плагина.

Я также пытался использовать код с Action в качестве переданного типа, чтобы позволить плагину передавать некоторый код для выполнения в AppDomain по умолчанию, но это не удалось с различными ошибками. Вот моя последняя попытка.

Основное применение:

[Serializable]
public sealed class DelegateWrapper<T1>
{
    private Action<T1> _someDelegate;

    public Action<T1> SomeDelegate
    {
        get
        {
            return _someDelegate;
        }
        set
        {
            if (value == null)
                _someDelegate = null;
            else
                _someDelegate = new myDelegateWrapper(value).Invoke;
        }
    }

    private sealed class myDelegateWrapper : MarshalByRefObject
    {
        public void Invoke(T1 input)
        {
            _delegate(input);
        }

        private Action<T1> _delegate;

        public myDelegateWrapper(Action<T1> dlgt)
        {
            _delegate = dlgt;
        }
    }
}


[Serializable]
public sealed class P
{
    public Action Action { get; }

    public P(Action action)
    {
        this.Action = action;
    }
}

private static readonly DelegateWrapper<P> PerformWrapper=new DelegateWrapper<P>();

public static void Init()
{
    PerformWrapper.SomeDelegate = p => p.Action();
}

Внутри нового AppDomain метод Perform вызывает execute.SomeDelegate.

Плагин (также выполняется в новом домене приложений):

Perform(new P(() =>
{
    //Third-party code
}));

Это приводит к исключению, говорящему о том, что он не может найти сборку плагина, которую я загрузил вручную в домене плагина. Я предполагаю, что он пытается загрузить его в домене по умолчанию. Есть ли способ обойти это?

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.IO.FileNotFoundException: Could not load file or assembly 'Plugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies

Полная трассировка стека здесь: https://pastebin.com/xZV7bXeV

...