Невозможно передать прозрачный прокси для ввода из 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);
Это может по крайней мере дать вам обходной путь к проблеме. Конечно, потенциальные недостатки не будут иметь проверку времени компиляции и/или более низкую производительность. Однако в зависимости от вашей ситуации это могут быть незначительные компромиссы.