利用C#的反射機制動態呼叫DLL類庫
阿新 • • 發佈:2019-02-19
1、使用Assembly類定義和載入程式集,載入在程式集清單中列出模組,以及從此程式集中查詢型別並建立該型別的例項。
2、使用MethodInfo瞭解方法的名稱、返回型別、引數、訪問修飾符(如pulic 或private)和實現詳細資訊(如abstract或virtual)等。使用Type的GetMethods或GetMethod方法來呼叫特定的方法。
一、建立用於反射呼叫的DLL
using System;
using System.Collections.Generic;
using System.Text;
namespace RefDll
{
/// <summary>
/// 建立需要被呼叫的DLL類庫
/// </summary>
public class RefTest
{
/// <summary>
/// 求和方法
/// </summary>
/// <param name="x">第一個值</param>
/// <param name="y">第二個值</param>
/// <param name="sum">結果(和)</param>
public void TestSum(int x,int y,out int sum)
{
sum = 0;
sum = x + y;
}
/// <summary>
/// 求和方法
/// 第二種方式
/// </summary>
/// <param name="x">第一個值</param>
/// <param name="y">第二個值</param>
/// <returns>結果(和)</returns>
public int TestSumTwo(int x, int y)
{
return x + y;
}
/// <summary>
/// 求和方法
/// 第三種方式
/// </summary>
/// <param name="x">第一個值</param>
/// <param name="y">第二個值</param>
/// <param name="sum">結果(和)</param>
public static void TestSumThree(int x, int y, out int sum)
{
sum = 0;
sum = x + y;
}
}
}
二、應用於反射的例子
注:可以建立一個控制檯的工程。
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Windows.Forms;
using System.IO;
namespace ReflectionLesson
{
/// <summary>
/// 反射類
/// 利用反射動態呼叫DLL類庫。
/// </summary>
public class ReflectionLesson
{
private string strDllName = "";
private string strClaName = "";
private string[] strMetName = null;
/// <summary>
/// 構造方法
/// </summary>
/// <param name="DllName">呼叫的DLL類庫名</param>
/// <param name="ClaName">呼叫的類名</param>
/// <param name="MetName">呼叫的方法名(陣列)</param>
public ReflectionLesson(string DllName, string ClaName, string[] MetName)
{
//獲取呼叫的DLL類庫
this.strClaName = ClaName;
this.strDllName = DllName;
this.strMetName = MetName;
}
/// <summary>
/// 利用反射動態呼叫DLL類庫
/// </summary>
public void ReflectionTest(int x,int y)
{
Assembly ass;
Type type;
object obj;
if (File.Exists(Application.StartupPath + "\\" + this.strDllName + ".dll"))
{
//獲取並載入DLL類庫中的程式集
ass = Assembly.LoadFile(Application.StartupPath + "\\" + this.strDllName + ".dll");
//獲取類的型別:必須使用名稱空間+類名稱
type = ass.GetType(this.strDllName + "." + this.strClaName);
//獲取類的方法:方法名稱
MethodInfo method1 = type.GetMethod(this.strMetName[0]);
MethodInfo method2 = type.GetMethod(this.strMetName[1]);
MethodInfo method3 = type.GetMethod(this.strMetName[2]);
//對獲取的類進行建立例項。//必須使用名稱空間+類名稱
obj = ass.CreateInstance(this.strDllName + "." + this.strClaName);
//開始搜尋方法
method1 = type.GetMethod(this.strMetName[0]);//方法的名稱1
method2 = type.GetMethod(this.strMetName[1]);//方法的名稱2
method3 = type.GetMethod(this.strMetName[2]);//方法的名稱3
object[] parts = new object[3];
parts[0] = x;
parts[1] = y;
//方法的呼叫
//注:如果呼叫的DLL類庫中方法是靜態的,那麼Invoke方法中第一個引數傳值為NULL。
// 如果方法不是靜態的,那麼Invoke方法中第一個引數傳值為 obj(上面那個被例項的物件)
method1.Invoke(obj, parts);
Console.WriteLine("呼叫的方法 " + this.strMetName[0] + ": " + x + " + " + y + " = " + parts[2]);
int sum1 = (int)method2.Invoke(obj, new object[] { x + 10, y + 10 });
Console.WriteLine("呼叫的方法 " + this.strMetName[1] + ": " + (x + 10) + " + " + (y + 10) + " = " + sum1);
object[] temParts = new object[3];
temParts[0] = x + 20;
temParts[1] = y + 20;
method3.Invoke(null, temParts);
Console.WriteLine("呼叫的方法 " + this.strMetName[2] + ": " + temParts[0] + " + " + temParts[1] + " = " + temParts[2]);
}
}
}
}
在Main 函式中可以輸入以下程式碼:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
namespace ReflectionLesson
{
class Program
{
static void Main(string[] args)
{
string dllname = "RefDll";
string claname ="RefTest";
string[] metname = new string[]{"TestSum","TestSumTwo","TestSumThree"};
ReflectionLesson refl = new ReflectionLesson(dllname, claname, metname);
refl.ReflectionTest(100,200);
}
}
}
2、使用MethodInfo瞭解方法的名稱、返回型別、引數、訪問修飾符(如pulic 或private)和實現詳細資訊(如abstract或virtual)等。使用Type的GetMethods或GetMethod方法來呼叫特定的方法。
一、建立用於反射呼叫的DLL
using System;
using System.Collections.Generic;
using System.Text;
namespace RefDll
{
/// <summary>
/// 建立需要被呼叫的DLL類庫
/// </summary>
public class RefTest
{
/// <summary>
/// 求和方法
/// </summary>
/// <param name="x">第一個值</param>
/// <param name="y">第二個值</param>
/// <param name="sum">結果(和)</param>
public void TestSum(int x,int y,out int sum)
{
sum = 0;
sum = x + y;
}
/// <summary>
/// 求和方法
/// 第二種方式
/// </summary>
/// <param name="x">第一個值</param>
/// <param name="y">第二個值</param>
/// <returns>結果(和)</returns>
public int TestSumTwo(int x, int y)
{
return x + y;
}
/// <summary>
/// 求和方法
/// 第三種方式
/// </summary>
/// <param name="x">第一個值</param>
/// <param name="y">第二個值</param>
/// <param name="sum">結果(和)</param>
public static void TestSumThree(int x, int y, out int sum)
{
sum = 0;
sum = x + y;
}
}
}
二、應用於反射的例子
注:可以建立一個控制檯的工程。
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Windows.Forms;
using System.IO;
namespace ReflectionLesson
{
/// <summary>
/// 反射類
/// 利用反射動態呼叫DLL類庫。
/// </summary>
public class ReflectionLesson
{
private string strDllName = "";
private string strClaName = "";
private string[] strMetName = null;
/// <summary>
/// 構造方法
/// </summary>
/// <param name="DllName">呼叫的DLL類庫名</param>
/// <param name="ClaName">呼叫的類名</param>
/// <param name="MetName">呼叫的方法名(陣列)</param>
public ReflectionLesson(string DllName, string ClaName, string[] MetName)
{
//獲取呼叫的DLL類庫
this.strClaName = ClaName;
this.strDllName = DllName;
this.strMetName = MetName;
}
/// <summary>
/// 利用反射動態呼叫DLL類庫
/// </summary>
public void ReflectionTest(int x,int y)
{
Assembly ass;
Type type;
object obj;
if (File.Exists(Application.StartupPath + "\\" + this.strDllName + ".dll"))
{
//獲取並載入DLL類庫中的程式集
ass = Assembly.LoadFile(Application.StartupPath + "\\" + this.strDllName + ".dll");
//獲取類的型別:必須使用名稱空間+類名稱
type = ass.GetType(this.strDllName + "." + this.strClaName);
//獲取類的方法:方法名稱
MethodInfo method1 = type.GetMethod(this.strMetName[0]);
MethodInfo method2 = type.GetMethod(this.strMetName[1]);
MethodInfo method3 = type.GetMethod(this.strMetName[2]);
//對獲取的類進行建立例項。//必須使用名稱空間+類名稱
obj = ass.CreateInstance(this.strDllName + "." + this.strClaName);
//開始搜尋方法
method1 = type.GetMethod(this.strMetName[0]);//方法的名稱1
method2 = type.GetMethod(this.strMetName[1]);//方法的名稱2
method3 = type.GetMethod(this.strMetName[2]);//方法的名稱3
object[] parts = new object[3];
parts[0] = x;
parts[1] = y;
//方法的呼叫
//注:如果呼叫的DLL類庫中方法是靜態的,那麼Invoke方法中第一個引數傳值為NULL。
// 如果方法不是靜態的,那麼Invoke方法中第一個引數傳值為 obj(上面那個被例項的物件)
method1.Invoke(obj, parts);
Console.WriteLine("呼叫的方法 " + this.strMetName[0] + ": " + x + " + " + y + " = " + parts[2]);
int sum1 = (int)method2.Invoke(obj, new object[] { x + 10, y + 10 });
Console.WriteLine("呼叫的方法 " + this.strMetName[1] + ": " + (x + 10) + " + " + (y + 10) + " = " + sum1);
object[] temParts = new object[3];
temParts[0] = x + 20;
temParts[1] = y + 20;
method3.Invoke(null, temParts);
Console.WriteLine("呼叫的方法 " + this.strMetName[2] + ": " + temParts[0] + " + " + temParts[1] + " = " + temParts[2]);
}
}
}
}
在Main 函式中可以輸入以下程式碼:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
namespace ReflectionLesson
{
class Program
{
static void Main(string[] args)
{
string dllname = "RefDll";
string claname ="RefTest";
string[] metname = new string[]{"TestSum","TestSumTwo","TestSumThree"};
ReflectionLesson refl = new ReflectionLesson(dllname, claname, metname);
refl.ReflectionTest(100,200);
}
}
}