Невозможно передать прозрачный прокси для ввода из AppDomain

Я пытаюсь создать объект в appdomain:

var type = typeof (CompiledTemplate);
var obj = (CompiledTemplate) domain.CreateInstanceAndUnwrap (
    type.Assembly.FullName, type.FullName);

Однако я всегда получаю следующую ошибку:

Невозможно передать прозрачный прокси для ввода "Mono.TextTemplating.CompiledTemplate".

Я запускаю .NET 4.0, а не Mono, несмотря на то, что может предложить пространство имен:)

Насколько я знаю, эта ошибка возникает, когда .NET думает, что тип и сборка не совпадают точно в двух доменах. Однако при отладке полное имя и местоположение идентичны. Только свойство Assembly.Codebase отличается - в дочернем домене AppDomain по какой-либо причине его расширение в верхнем регистре до "DLL".

Я попытался добавить обработчик AssemblyResolve в AppDomain, который использует Assembly.LoadFrom для загрузки имени файла явно, но расширение CodeBase по-прежнему получает верхний регистр. Поскольку исходная сборка также была загружена Assembly.LoadFrom(через Mono.Addins), разница между значениями CodeBase кажется очень странной.

Любые предложения по устранению или устранению этой проблемы?

Ответ 1

Не могли бы вы столкнуться с проблемой с контекстами загрузки сборки? (например, см. здесь) У вас есть тип, который явно в контексте загрузки (потому что вы используете typeof(CompiledTemplate)), но вы говорите, что тип вторичного AD загружается в контекст load-from...

Вы проверили с fuslogvw, чтобы точно определить, какие сборки загружаются? Трассировка fuslog также расскажет вам, загружаются ли сборки в разные контексты.

Ответ 2

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

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

Это типичная проблема, когда "DLLHell" распространяется на "GACAndDLLHell". "GACONLYHeaven" - лучшее место...:).

То, что имена файлов тонко отличаются (расширение .DLL имеет другой случай), подразумевает, что одна и та же DLL загружается из двух мест (то есть: GAC нечувствителен к регистру/всегда нижний регистр в именах файлов IIRC).

Абсолютный класс или, желательно, интерфейс - вот что вам нужно здесь.

Если вы не можете внести изменения в базу кода, я бы, во-первых, очень убедился, что DLL существует только в одном месте на диске (или 0 мест на диске, если он загружается из GAC). Копия DLL, которая содержит тип: "CompiledTemplate" в папке вашего приложения /bin, будет настоящим виновником...?

Является ли этот новый код или существующий код, который по какой-то причине не работает?

Ответ 3

Возможно, вы можете использовать ключевое слово dynamic вместо того, чтобы отнести его к определенному типу:

var type = typeof (CompiledTemplate);
dynamic obj = domain.CreateInstanceAndUnwrap (
    type.Assembly.FullName, type.FullName);

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