Какими способами я могу отправлять данные из подключаемого модуля через домен приложения, который запускает событие в основном приложении на C#?

У меня есть основное приложение, которое загружает некоторые плагины. Эти подключаемые модули загружаются и запускаются в отдельных доменах приложений с использованием класса, наследуемого от «MarshalByRefObject»; Это все работает нормально.

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

Каковы наилучшие способы отправки запроса от подключаемого модуля через домен приложения в основное приложение?

ОБНОВЛЕНИЕ

В качестве обновления вопроса я хочу отправить данные по домену приложения, которые заставляют основное приложение что-то делать, например, операцию «Файл-> Новый» или вызов «GetSomeData()». При этом мне нужно заставить плагин ждать, пока основное приложение завершит все, что он делает, но также иметь возможность решить, на стороне основного приложения, выполнять ли запрошенную функцию/событие.

Я делал это, передавая плагину интерфейс. Этот интерфейс был реализован классом в основном приложении, который определял некоторые события. Затем основное приложение может подписаться на эти события, а плагин может активировать основные функции приложения. Проблема в том, что интерфейс ссылался только на класс, как это было, когда я передал интерфейс. То есть, если я создал класс без подписки на события, то передал интерфейс следующим образом:

CallbackClass myCallbackClass = new CallbackClass();
pluginInterface.HeresMyCallbackClass((ICallbackClass)myCallbackClass);

плагин получит интерфейс, но никакие изменения исходного класса не распространятся. Итак, добавление:

myCallbackClass.MyMainAppEvent += new MainEventHandler(MyMainAppFunction);

не изменит версию события плагина. Плагин может сделать это:

//code within plugin
ICallbackClass callToMainApp;
public HeresMyCallbackClass(ICallbackClass cbClass)
{
    callToMainApp = cbClass;
}

public CallAMainAppFunction()
{
    callToMainApp.CallTheSubscribedFunction(); //This is where it all goes wrong
}

... но событие, которое он пытается вызвать, равно null. Теперь это не проблема, если я сначала подпишусь на событие в основном приложении, а затем передам интерфейс:

CallbackClass myCallbackClass = new CallbackClass();
myCallbackClass.MyMainAppEvent += new MainEventHandler(MyMainAppFunction); //Subscribe first
pluginInterface.HeresMyCallbackClass((ICallbackClass)myCallbackClass);

Затем плагин может вызвать CallTheSubscribedFunction(), и событие сработает в основном приложении. Мне нужно иметь возможность подписаться на подобные события по запросу, потому что некоторые вещи/события/данные в основном приложении доступны в разное время.

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

Если у кого-то есть предложения, пожалуйста, дайте мне знать. Опять же, моя цель — позволить плагину инициировать событие в основном приложении, дождаться завершения основного приложения, а затем продолжить его выполнение, где основное приложение может быть подписано или не подписано на события.

Обновление 2

Я понимаю, что приведенная выше информация предназначена для моего приложения, но я также ищу общие предложения. Итак, если использование потоков является вариантом, дайте мне знать, как может работать общий случай. Если другой случай будет работать лучше, и мне нужно сделать некоторые изменения, чтобы реализовать его, дайте мне знать и об этом. Просто ищу предложения здесь. Спасибо.


person Mike Webb    schedule 02.02.2011    source источник
comment
Именованные каналы, EventWaitHandle, WCF, удаленное взаимодействие. Выберите один :) В зависимости от того, что вам нужно сделать, выберите тот, который дает вам самый чистый код.   -  person Mikael Svenson    schedule 03.02.2011
comment
@Mike, ты на правильном пути, то есть используешь шаблон Observer. Вероятно, вам просто нужно сгладить некоторые острые углы. @Mikael, нет необходимости в WCF и других внепроцессных IPC. Второй домен приложения является хостом основного приложения, поэтому он находится в процессе обмена данными.   -  person Shiv Kumar    schedule 03.02.2011
comment
@Shiv Kumar - Под наблюдателем вы имеете в виду опрос плагина?   -  person Mike Webb    schedule 03.02.2011
comment
@Майк, нет, не опрос. Но концепция подписки, которую вы используете. Если вы не знакомы с паттерном наблюдателя, вам может помочь его чтение.   -  person Shiv Kumar    schedule 03.02.2011
comment
@Shiv Kumar - Поместите свой ответ о процессе наблюдателя в ответ, и я приму его. Это было именно то, что мне было нужно.   -  person Mike Webb    schedule 07.02.2011
comment
@Mike, спасибо, что сообщили мне! И +1 за это.   -  person Shiv Kumar    schedule 08.02.2011


Ответы (2)


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

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

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

Имеет ли это смысл?

person Shiv Kumar    schedule 07.02.2011

Убедитесь, что ваш CallbackClass наследуется от MarshalByRefObject. В противном случае копия класса обратного вызова будет создана по другую сторону границы домена приложения, что сделает невозможным взаимодействие между доменами приложений.

person Chris Shain    schedule 04.02.2011