问题
I have a .cs file like
namespace SomeNamepace
{
public struct SomeStruct
{
....
}
public static class SomeClass
{
....
}
So far I use it with PythonNET like
import clr
clr.AddReference('c:\\Test\Module.dll')
from SomeNamepace import SomeClass, SomeStruct
SomeClass.SomeMethod(...)
My problem is now that I need to work with dlls with identical names and no version number set, so PythonNET will not see them as two different dlls but as the same. Even if I import them using the full path with AddReference.
Now I would like to use them explicitly as stated here:
Python for .NET: Using same .NET assembly in multiple versions
like
lib = clr.AddReference('c:\\Test\Module.dll')
I tried a lot of things to create an instance of SomeClass
like
lib.SomeNamespace.SomeClass()
or
import System
System.Activator.CreateInstance(lib.GetType('SomeNamespace.SomeClass'))
or using the the methods Initialize
or CreateInstance
or as mentioned in the link below
from System import Type
type1 = lib.GetType('SomeNamespace.SomeClass')
constructor1 = type1.GetConstructor(Type.EmptyTypes)
In the end everything failed, something not found, has no method, etc. etc.
What would be the correct syntax to do this?
回答1:
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 anddll_ref
and Reflection are used to get the methodsusing 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 versionSystem.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)
来源:https://stackoverflow.com/questions/49942487/python-for-net-how-to-explicitly-create-instances-of-c-sharp-classes-using-dif