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

У меня есть файл.cs, как

namespace SomeNamepace
{


    public struct SomeStruct
    {
        ....
    }

    public static class SomeClass
    {
        ....
    }

До сих пор я использую его с PythonNET, как

import clr
clr.AddReference('c:\\Test\Module.dll')
from SomeNamepace import SomeClass, SomeStruct

SomeClass.SomeMethod(...)

Моя проблема сейчас в том, что мне нужно работать с dll с одинаковыми именами и без номера версии, поэтому PythonNET не будет видеть их как две разные dll, но как одинаковые. Даже если я импортирую их, используя полный путь с AddReference.

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

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

лайк

lib = clr.AddReference('c:\\Test\Module.dll')

Я перепробовал много вещей, чтобы создать экземпляр SomeClass лайк

lib.SomeNamespace.SomeClass()

или же

import System
System.Activator.CreateInstance(lib.GetType('SomeNamespace.SomeClass'))

или используя методы Initialize или же CreateInstance

или как указано в ссылке ниже

from System import Type
type1 = lib.GetType('SomeNamespace.SomeClass')
constructor1 = type1.GetConstructor(Type.EmptyTypes)    

В конце концов все не удалось, что-то не найдено, не имеет метода и т. Д. И т. Д.

Какой будет правильный синтаксис для этого?

1 ответ

Решение

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

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

В этом случае имена, к которым вы обращаетесь через модули CLR, всегда будут поступать из первой загруженной версии сборки (которая всегда будет выигрывать во внутренних средах выполнения).

Размещенное там решение больше не работает, я полагаю, что функция.NET устарела. Но есть решение для этого. Вместо использования 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

Из документов на LoadFile

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

Методы, которые не работают:

  • добавление ссылок на другие библиотеки DLL с разными версиями, используя dll_ref = clr.AddReference(f) не работает, даже если имя файла указано явно и dll_ref и Reflection используются для получения методов

  • используя длинное имя (например, 'MyNamespace, Version=1.0.0.1, Culture=neutral, PublicKeyToken=null' с System.Reflection.Assembly.Load с версией все равно будет использовать первую версию

  • System.Reflection.Assembly.LoadFrom не работает с несколькими версиями одной и той же библиотеки DLL, если сборка с таким же идентификатором уже загружена. LoadFrom возвращает загруженную сборку, даже если указан другой путь. ( Документ LoadFrom)

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