AppDomian.Load Exception
От: AHA Россия  
Дата: 08.12.04 11:25
Оценка:
Привет,
При попытке загрузить сборку в AppDomain получаю Exception: "Insufficient state to deserialize the object. More information is needed."

Проблема в следующем:
Есть куча DLL (созданных налету через ICodeCompiler->CompileAssemblyFromFile по описанию WebService).
Раньше я загружал их так:
    String *sType = String::Format ( S"{0}.{1}", sDynamicNameSpace, sClassName );
    Assembly *oAssembly = Assembly::LoadFrom ( sFileNameDll );
    Type *tDynamic = oAssembly->GetType ( sType );
    Object *oObject = Activator::CreateInstance ( tDynamic );
    Object *oResult = tDynamic->InvokeMember ( .............


Сейчас потребовалось переодически эти DLL обновлять, для этого надо грузить их в Domain.
Сделал как в MSDN:
Byte SoapTest::LoadFile ( String *sFileName)[]
{
    FileStream *oFileStream = new FileStream ( sFileName, FileMode::Open );
    Byte arBuffer[] = new Byte[(int) oFileStream->Length];
    oFileStream->Read ( arBuffer, 0, arBuffer->Length );
    oFileStream->Close ( );
    return arBuffer;
}

..
    AppDomainSetup *oAppDomainSetup = new AppDomainSetup ( );
    oAppDomainSetup->ApplicationName = sDynamicNameSpace;
    oAppDomainSetup->ApplicationBase = sDllPath;
    oAppDomainSetup->ShadowCopyFiles = S"true";

    Evidence *oEvidence = new Evidence ( AppDomain::CurrentDomain->Evidence );
    
    AppDomain *oAppDomain = AppDomain::CreateDomain ( sDynamicNameSpace, oEvidence, oAppDomainSetup );

    oAppDomain->Load ( LoadFile ( sFileNameDll ) );


При этом получаю описанный выше — Exception. В чем может быть проблема ?

PS: CreateInstanceFromAndUnwrap работает, но непонятно как из полученного Proxy получить сам объект, т.к. Type заранее не известен (есть только TypaName)

Object *oObject = oAppDomain->CreateInstanceFromAndUnwrap ( sFileNameDll, sType );
AppDomian.Load Exception
От: Аноним  
Дата: 08.12.04 11:49
Оценка: 3 (1)
AppDomain.Load пытается провести через ремотинг Assembly, если эта же сборка отсутствует в вызывающем домене, то происходит ошибка сериализации.

Если надо грузить сборки в один домен, а использовать их из другого, то нужен
а) агент — загрузчик — загруженная в основной домен сборка, которая грузится в дочерний через Load(AssemblyName) при этом надо учесть, что если CodeBase дочернего домена иной, нежели у главного, то файл сборки ОБЯЗАН лежать в этой папке или в GAC, так как несмотря на наличие в AssemblyName пути на диске, загрузчик все равно ведет себя одинаково — проверить GAC, проверить приватную директорию, проверить пробинги

б)для ремотинга обязательным условием является присутствие метаданных участвующих во взаимодействии классов у обоих участников взаимодействия, из другого домена нельзя получить удаленный экземпляр класса, если метадщанных нет в вызывающем домене.
Так как грузить сами ваши сборки в основной домен нельзя (вы же их хотите обновлять) значит и ваше приложение и ваши сборки должны иметь ссылки на ОБЩУЮ сборку с основными классами и интерфейсами, которые и будут участвовать во взаимодействии.

Примерный сценарий
То есть например вы грузите в основной домен и в дочерний домен общую сборку, содержащую
а) интерфейс IPlugin
б) сериализуемый класс — дескриптор плагина
б) класс унаследованный от MarshallByRef типа PluginEnumerator, который возвращает список всех классов, поддерживающих IPlugin и обнаруженных в своем домене
г) класс — загрузчик плагина, инстанцирующий плагин и передающий ссылку на IPlugin, скажем PluginLoader

потом в домен грузятся ваши сборки, классы в которых реализуют интерфейс IPlugin

Так, теперь есть два домена, с общей сборкий и некими неизвестными и глубоко отделенными от основного домена сборками внутри дочернего. Задача — инстанцировать некий Plugin1, про который основной домен ровным счетом ничего не знает.

Для этого основной домен делает:
1) создает через активатор экземпляр PluginEnumerator (так как он MarshallByRef, то его исполнение будет происходить в дочернем домене)
2) получаем у енумератора список всех плагинов в дочернем домене, возвращенных в виде массива дескрипторов плагинов (в самом простом виде это просто список каких-то ключей или просто количество плагинов для доступа по номеру)
3) если понадобился удаленный экземпляр нужного IPlugin, мы опять же в дочернем домене создаем экземпляр PluginLoader (так же MarshallByRef) и в качестве параметра передаем полученный на 2-м этапе дескриптор. PluginLoadder загружает конкретный класс и передает обратно ссылку на его интерфейс IPlugin, естественно что полученный Proxy вам уже не удастся к чему-то еще привести, так как в основном домене есть только метаданные об IPlugin и именно этот интерфейс маршалится через ремотинг

Таким образом мы получаем что хотели. Главное запомнить одно, что-то общее у доменов быть должно для взаимодействия, просто так лазить в соседний домен и грузить из него классы концептуально нельзя.


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re: Thanks, буду разбираться (-)
От: AHA Россия  
Дата: 08.12.04 13:13
Оценка:
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.