Python для.NET: использование одной сборки.NET в нескольких версиях

Моя проблема: у меня есть сборка в 2 версиях, и я хочу использовать их одновременно в своем проекте Python.

.NET библиотеки установлены в GAC (MSIL) с тем же общедоступным токеном:

lib.dll (1.0.0.0)
lib.dll (2.0.0.0)

В Python я хочу что-то подобное:

import clr
clr.AddReference("lib, Version=1.0.0.0, ...")
from lib import Class
myClass1 = Class()
myClass1.Operation()

*magic*

clr.AddReference("lib, Version=2.0.0.0, ...")
from lib import class
myClass2 = Class()
myClass2.Operation()
myClass2.OperationFromVersion2()

*other stuff*

# both objects should be accessibly
myClass1.Operation() 
myClass2.OperationFromVersion2()

Есть способ сделать это? Что-то с AppDomains или bindingRedirect?

Примечание. Конечно, myClass1.operationFromVersion2() может завершиться ошибкой...

2 ответа

Решение

Ну, я нашел решение: Python для.NET также поддерживает Reflection!

Вместо

clr.AddReference("lib, Version=1.0.0.0, ...")

Вы должны использовать

assembly1 = clr.AddReference("lib, Version=1.0.0.0, ...")

С этой сборкой вы можете использовать все вещи Reflection, как в C#. В моем примере я должен использовать следующий код (то же самое для версии 2):

from System import Type
type1 = assembly1.GetType(...)
constructor1 = type1.GetConstructor(Type.EmptyTypes)
myClass1 = constructor1.Invoke([])

Я не мог заставить его работать, используя принятый ответ. Вот мое решение.

Вместо использования PythonNet вы должны использовать.NET Framework напрямую:

import System

dll_ref = System.Reflection.Assembly.LoadFile(fullPath)
print(dll_ref.FullName)
print(dll_ref.Location)

Убедитесь, что используется правильная DLL.

Чтобы использовать несколько библиотек DLL с одной и той же версией, просто загрузите ее в другую переменную

another_dll_ref = System.Reflection.Assembly.LoadFile(anotherFullPath)

Теперь вы можете использовать объекты из указанной библиотеки DLL.

Экземпляр общедоступного нестатического класса

some_class_type = dll_ref.GetType('MyNamespace.SomeClass')
my_instance = System.Activator.CreateInstance(some_class_type)
my_instance.a = 4 # setting attribute
my_instance.b('whatever') # calling methods

Вызов метода в общедоступном статическом классе

some_class_type = dll_ref.GetType('MyNamespace.SomeClass')
method = some_class_type.GetMethod('SomeMethod')
# return type and list of parameters
method.Invoke(None, [1, 2.0, '3']) 

Создание экземпляра структуры

some_struct_type = dll_ref.GetType('MyNamespace.SomeStruct')
my_struct = System.Activator.CreateInstance(some_struct_type)
my_struct.a = 3

(взято из моего вопроса Python для.NET: Как явно создавать экземпляры классов C#, используя разные версии одной и той же DLL?)

Другие вопросы по тегам