问题
I can't get a grip on how the various "Init", "Accumulate" ... methods work, to enable calling a method located inside a DLL, from VB.Net code.
Let's say the method to call has the following signature :
public double ComputeMeanPosition(ref SortedList<DateTime, double> posByTime)
Would you please kindly point me to an actual example of the use of the methods, or simply give me a few hints as how to actually pass the parameters to the method, call it and fetch the results ?
@Olivier Jacot-Descombes: I definitely prefix the class name by the namespace name, but yet fail to be able to reach the object. In fact I am surprised that your kind suggestion does not involve the following methods, displayed through introspection of the loaded DLL :
Type: MyClassName
Method: Void Init()
Method: Void Accumulate(System.Data.SqlTypes.SqlDouble, System.Data.SqlTypes.SqlDateTime, System.Data.SqlTypes.SqlBoolean)
Method: Void Merge(MyClassName)
Method: System.Data.SqlTypes.SqlDouble Terminate()
Method: Void Write(System.IO.BinaryWriter)
Method: Void Read(System.IO.BinaryReader)
Method: Boolean Equals(System.Object)
Method: Int32 GetHashCode()
Method: System.String ToString()
Method: System.Type GetType()
EDIT
In fact I have a code similar to the following one, that successfully manages to inspect the DLL and gets several types and methods out of it, giving the following results above for the method I would like to call.
Here is the code
For Each oneModule As Reflection.Module In useAssembly.GetLoadedModules() Console.WriteLine(" - " & oneModule.Name) For Each oneType As System.Type In oneModule.GetTypes() Console.WriteLine(" Type: " & oneType.Name) For Each oneField As Reflection.FieldInfo In oneType.GetFields() Console.WriteLine(" Field: " & oneField.ToString()) Next oneField For Each oneMethod As Reflection.MethodInfo In oneType.GetMethods() Console.WriteLine(" Method: " & oneMethod.ToString()) [[ ADD "Invoke" here ?]] Next oneMethod Next oneType Next oneModule
At the end, it seems that the [[...]] is at the place where the Invoke method should be called to call the method of my choice, but that is where I'm stuck... Would I need to build an object before calling it ? How should I pass it the parameters ? How to get the result ?
回答1:
Something like this should work:
using System;
using System.Reflection;
using System.IO;
public class MainClass
{
public static int Main(string[] args)
{
Assembly a = null;
try
{
a = Assembly.Load("YourLibraryName");
}
catch(FileNotFoundException e)
{Console.WriteLine(e.Message);}
Type classType = a.GetType("YourLibraryName.ClassName");
object obj = Activator.CreateInstance(classType);
object[] paramArray = new object[1];
paramArray[0] = new SortledList<DateTime, double>();
MethodInfo mi = classType.GetMethod("ComputeMeanPosition");
mi.Invoke(obj, paramArray);
return 0;
}
}
For VB.NET:
Imports System
Imports System.Reflection
Imports System.IO
Public Class MainClass
Public Shared Function Main(args As String()) As Integer
Dim a As Assembly = Nothing
Try
a = Assembly.Load("YourLibraryName")
Catch e As FileNotFoundException
Console.WriteLine(e.Message)
End Try
Dim classType As Type = a.[GetType]("YourLibraryName.ClassName")
Dim obj As Object = Activator.CreateInstance(classType)
Dim [paramArray] As Object() = New Object(0) {}
[paramArray](0) = New SortledList(Of DateTime, Double)()
Dim mi As MethodInfo = classType.GetMethod("ComputeMeanPosition")
mi.Invoke(obj, [paramArray])
Return 0
End Function
End Class
Tested and this worked:
Dim a As Assembly = Nothing
Try
a = Assembly.Load("TestLib")
Catch ex As FileNotFoundException
Console.WriteLine(ex.Message)
End Try
Dim classType As Type = a.[GetType]("TestLib.Class1")
Dim obj As Object = Activator.CreateInstance(classType)
Dim [paramArray] As Object() = New Object(0) {}
[paramArray](0) = New SortedList(Of DateTime, Double)()
Dim mi As MethodInfo = classType.GetMethod("ComputeMeanPosition")
mi.Invoke(obj, [paramArray])
回答2:
This is not the actual code, because I'm not in sitting in front of an actual c# editor, but something like this
// using System.Reflection required
// first load the external assembly into the appdomain and
// create an instance of the object
var assembly = Assembly.Load("Path to the Assembly");
var type = assembley.GetType("TheNameOfTheClass");
var ctor = type.GetConstuctor();
var object = ctor.Invoke(); // assuming an empty construtor, else you'll need to pass in data
// next invoke the method
var methodInfo = assembly.GetMethodByName("ComputeMeanPosition");
var param = new SortedList<DateTime, double>();
var result = methodInfo.Invoke(object, new object[] { param });
回答3:
You can call this method as if was declared like this in VB
Public Function ComputeMeanPosition( _
ByRef posByTime As SortedList(Of DateTime, Double)) As Double
Note: I used this online snippet converter to convert the C# code to VB. You have to add an empty method body {}
to the C# method header before converting it.
public double ComputeMeanPosition(ref SortedList<DateTime, double> posByTime) {}
As this method is not declared as static
in C# (Shared
in VB) you first need to create an object. The method is most likely declared inside a class. Let's say the class was named "MyClass", then you would have to write something like this
Dim posByTime = New SortedList(Of DateTime, Double)()
Dim obj = New MyClass()
Dim result As Double = obj.ComputeMeanPosition(posByTime)
If the constructor (the New
method) declares arguments, you will have to pass them when creating the object
Dim obj = New MyClass(arg1, arg2, ...)
Depending on what ComputeMeanPosition
expects, you will have to add items to the list posByTime
before calling it.
If the method was declared as static
in C# (Shared
in VB), you would qualify it with the class name, instead of creating an object.
Dim posByTime = New SortedList(Of DateTime, Double)()
Dim result As Double = MyClass.ComputeMeanPosition(posByTime)
UPDATE
If you load the assembly dynamically you will probably do something like this
Dim ass As Assembly = Assembly.LoadFrom("C:\SomePath\MyDll.dll")
Dim obj As Object = ass.CreateInstance("MyClass", True)
Dim posByTime = New SortedList(Of DateTime, Double)()
Dim result As Double = obj.ComputeMeanPosition(posByTime)
And you will have to set the Option Strict Off
for late binding.
If the constructor requires arguments, you will have to pass them to another overload of CreateInstance
Dim args = new Object() { arg1, arg2, ... }
Dim obj As Object = ass.CreateInstance("MyClass", True, _
BindingFlags.Public Or BindingFlags.Instance, Nothing, Nothing, _
args, Nothing, Nothing)
来源:https://stackoverflow.com/questions/10450935/how-to-call-a-method-located-inside-a-c-sharp-dll-from-vb-net-with-late-bindin