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'))
或使用方法 Initialize
或 CreateInstance
或下面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)
我有一个类似
的 .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'))
或使用方法 Initialize
或 CreateInstance
或下面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)