PowerShell 2 новый объект "Не удается найти тип ..." исключение, когда экземпляр класса .net реализовал интерфейс из внешней библиотеки - PullRequest
4 голосов
/ 17 ноября 2010

Я обнаружил проблему, которую довольно легко воспроизвести.Посоветуйте, пожалуйста, есть ли способ обойти это?

Существуют две библиотеки .Net libraryA.dll и libraryB.dll.И каждая библиотека имеет один интерфейс InterfaceA и InterfaceB.ClassAA реализует InterfaceA и живет в libraryA.ClassAB реализует InterfaceB и живет в той же библиотеке A.Точно так же ClassBB - LibraryB - InterfaceB;ClassBA - LibraryB - InterfaceA

New-Object работает правильно, когда создаются ClassAA и ClassBB, но не ClassAB или ClassBA.Им постоянно не удается создать экземпляр.

Вот вам код PowerShell

[System.Reflection.Assembly]::LoadFile(‘c:\LibraryA.dll’)
[System.Reflection.Assembly]::LoadFile(‘c:\LibraryB.dll’)

$obj1 = new-object -typeName ClassAA   (IT WORKS)
$obj2 = new-object -typeName ClassBB   (IT WORKS)
$obj3 = new-object -typeName ClassAB   (EXCEPTION THROWN)
$obj4 = new-object -typeName ClassBA   (EXCEPTION THROWN)

Большое спасибо,

Андрей

Ответы [ 2 ]

6 голосов
/ 03 января 2013

Вместо ::LoadFile используйте:

[System.Reflection.Assembly]::LoadFrom(‘c:\LibraryA.dll’)
[System.Reflection.Assembly]::LoadFrom(‘c:\LibraryB.dll’)

Когда вы используете :: LoadFrom сборка будет загружена в контекст с каталогом, из которого она была загружена, ссылки на сборки в этом же каталоге будут автоматически разрешены. :: LoadFile предназначен для загрузки сборок, которые имеют общую идентификацию, но находятся в разных каталогах и не сохраняют никакого контекста загрузки, поэтому ссылочные сборки не разрешаются.

3 голосов
/ 21 мая 2011

Ответ на этот вопрос решает вашу проблему: Как заставить Дополнительные типы PowerShell использовать Добавленные типы

Ключ должен использовать событие AppDomain.CurrentDomain.AssemblyResolve.

Например, вы можете добавить класс AssemblyResolver (из приведенного выше поста) в LibraryA и затем использовать [Utils.AssemblyResolver] :: AddAssemblyLocation ("LibraryB.dll"), чтобы при необходимости получить ссылку на LibraryB. 1007 *

Или, просто чтобы доказать свою точку зрения:

[System.AppDomain]::CurrentDomain.add_assemblyResolve({
    If ($args[1].Name.StartsWith("LibraryB"))
    {
        Return [System.Reflection.Assembly]::LoadFile("C:\LibraryB.dll")
    }
    Else
    {
        Return $Null
    }
})

Обратите внимание, что в приведенном выше примере у вас круговая зависимость: LibraryA ссылается на LibraryB, а LibraryB ссылается на LibraryA. Возможно, вы сначала захотите это исправить - при условии, что у вас есть то же самое в вашем реальном проекте ...

...