Python for .NET: How to explicitly create instances of C# classes using different versions of the same DLL?

偶尔善良 提交于 2019-11-29 07:13:05

I found an old mailing list conversation that might explain it

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).

The solution posted there does not work anymore, I guess the .NET function has been depracated. But there is a solution to this. Instead of using PythonNet you must use the .NET framework directly:

import System

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

Check that the correct DLL is used.

To use multiple DLLs with the same version just load it to another variable

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

Now you can use objects from the specified dll.

Instance of a public non-static 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

Calling a method in a public static 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']) 

Creating a instance of a struct

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

From the docs on 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.

Methods that don't work:

  • adding references to other DLLs with different versions using dll_ref = clr.AddReference(f) does not work, even if the file name is specified explicitly and dll_ref and Reflection are used to get the methods

  • using a longname (like 'MyNamespace, Version=1.0.0.1, Culture=neutral, PublicKeyToken=null' with System.Reflection.Assembly.Load with the version will still use the first version

  • System.Reflection.Assembly.LoadFrom does not work with multiple version of the same DLL if an assembly with the same identity is already loaded. LoadFrom returns the loaded assembly even if a different path was specified. (Doc LoadFrom)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!