Python for .NET:如何使用同一 DLL 的不同版本显式创建 C# 类 的实例?

Python for .NET: How to explicitly create instances of C# classes using different versions of the same 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 的完整路径导入它们。

现在我想按照此处所述明确使用它们:

喜欢

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

我尝试了很多方法来创建 SomeClass 的实例,比如

lib.SomeNamespace.SomeClass()

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

或使用方法 InitializeCreateInstance

或下面link中提到的

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

最后一切都失败了,找不到东西,没有方法等等等等

执行此操作的正确语法是什么?

我找到了一个旧的 mailing list 对话可以解释它

Things get a lot more complicated if you need to load more than one version of a particular assembly (or more likely, you have a dependency on some library the does so).

In this case, the names you access via the CLR modules will always come from the first version of the assembly loaded (which will always win in the internals of the runtime).

那里发布的解决方案不再有效,我想 .NET 功能已被取消。但是有一个解决方案。您必须直接使用 .NET 框架,而不是使用 PythonNet:

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 中的对象了。

public 非静态实例 class

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

在 public 静态 class

中调用方法
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

上的文档

Use the LoadFile method to load and examine assemblies that have the same identity, but are located in different paths.LoadFile does not load files into the load-from context, and does not resolve dependencies using the load path, as the LoadFrom method does.LoadFile is useful in this limited scenario because LoadFrom cannot be used to load assemblies that have the same identities but different paths; it will load only the first such assembly.

无效的方法:

  • 使用dll_ref = clr.AddReference(f)添加对不同版本的其他DLL的引用不起作用,即使明确指定了文件名并且使用dll_ref和反射来获取方法

  • using a longname (like 'MyNamespace, Version=1.0.0.1, Culture=neutral, PublicKeyToken=null' with System.Reflection.Assembly.Load with the version 仍将使用第一个版本

  • 如果已加载具有相同标识的程序集,
  • System.Reflection.Assembly.LoadFrom 不适用于同一 DLL 的多个版本。 LoadFrom returns 加载的程序集,即使指定了不同的路径。 (Doc LoadFrom)