zoukankan      html  css  js  c++  java
  • 利用C#的反射机制动态调用DLL类库

    利用C#的反射机制动态调用DLL类库

    最近由于业务要求,需要动态调用DLL类库,所以研究了一下,感觉还好也不太难,今天就把自己理解的写了一个小例子(已经通过VS2005跑通),供大家一起研究和探讨,有理解不当的地方还请高手们多多指正,谢谢啦!

    好,在这之前我先把反射所需要使用的几个类给大家列一下:

    1、使用Assembly类定义和加载程序集,加载在程序集清单中列出模块,以及从此程序集中查找类型并创建该类型的实例。

    2、使用MethodInfo了解方法的名称、返回类型、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。使用Type的GetMethods或GetMethod方法来调用特定的方法。

    一、创建用于反射调用的DLL

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Text;
     4 
     5 namespace RefDll
     6 {
     7     /// <summary>
     8     /// 创建需要被调用的DLL类库
     9     /// </summary>
    10     public class RefTest
    11     {
    12         /// <summary>
    13         /// 求和方法
    14         /// </summary>
    15         /// <param name="x">第一个值</param>
    16         /// <param name="y">第二个值</param>
    17         /// <param name="sum">结果(和)</param>
    18         public void TestSum(int x,int y,out int sum)
    19         {
    20             sum = 0;
    21             sum = x + y;
    22         }
    23 
    24         /// <summary>
    25         /// 求和方法
    26         /// 第二种方式
    27         /// </summary>
    28         /// <param name="x">第一个值</param>
    29         /// <param name="y">第二个值</param>
    30         /// <returns>结果(和)</returns>
    31         public int TestSumTwo(int x, int y)
    32         {
    33             return x + y;
    34         }
    35 
    36         /// <summary>
    37         /// 求和方法
    38         /// 第三种方式
    39         /// </summary>
    40         /// <param name="x">第一个值</param>
    41         /// <param name="y">第二个值</param>
    42         /// <param name="sum">结果(和)</param>
    43         public static void TestSumThree(int x, int y, out int sum)
    44         {
    45             sum = 0;
    46             sum = x + y;
    47         }
    48 
    49     }
    50 }

    二、应用于反射的例子

        注:可以创建一个控制台的工程。

     1  using System;
     2 using System.Collections.Generic;
     3 using System.Text;
     4 using System.Reflection;
     5 using System.Windows.Forms;
     6 using System.IO;
     7 
     8 namespace ReflectionLesson
     9 {
    10     /// <summary>
    11     /// 反射类
    12     /// 利用反射动态调用DLL类库。
    13     /// </summary>
    14     public class ReflectionLesson
    15     {
    16         private string strDllName = "";
    17         private string strClaName = "";
    18         private string[] strMetName = null;
    19         /// <summary>
    20         /// 构造方法
    21         /// </summary>
    22         /// <param name="DllName">调用的DLL类库名</param>
    23         /// <param name="ClaName">调用的类名</param>
    24         /// <param name="MetName">调用的方法名(数组)</param>
    25         public ReflectionLesson(string DllName, string ClaName, string[] MetName)
    26         {
    27             //获取调用的DLL类库
    28             this.strClaName = ClaName;
    29             this.strDllName = DllName;
    30             this.strMetName = MetName;
    31         }
    32 
    33         /// <summary>
    34         /// 利用反射动态调用DLL类库
    35         /// </summary>
    36         public void ReflectionTest(int x,int y)
    37         {
    38             Assembly ass;
    39             Type type;
    40             object obj;
    41             if (File.Exists(Application.StartupPath + "\\" + this.strDllName + ".dll"))
    42             {
    43                 //获取并加载DLL类库中的程序集
    44                 ass = Assembly.LoadFile(Application.StartupPath + "\\" + this.strDllName + ".dll");
    45 
    46                 //获取类的类型:必须使用名称空间+类名称
    47                 type = ass.GetType(this.strDllName + "." + this.strClaName);
    48 
    49                 //获取类的方法:方法名称
    50                 MethodInfo method1 = type.GetMethod(this.strMetName[0]);
    51                 MethodInfo method2 = type.GetMethod(this.strMetName[1]);
    52                 MethodInfo method3 = type.GetMethod(this.strMetName[2]);
    53 
    54                 //对获取的类进行创建实例。//必须使用名称空间+类名称
    55                 obj = ass.CreateInstance(this.strDllName + "." + this.strClaName);
    56 
    57                 //开始搜索方法
    58                 method1 = type.GetMethod(this.strMetName[0]);//方法的名称1
    59                 method2 = type.GetMethod(this.strMetName[1]);//方法的名称2
    60                 method3 = type.GetMethod(this.strMetName[2]);//方法的名称3
    61 
    62                 object[] parts = new object[3];
    63                 parts[0] = x;
    64                 parts[1] = y;
    65 
    66                 //方法的调用
    67                 //注:如果调用的DLL类库中方法是静态的,那么Invoke方法中第一个参数传值为NULL。
    68                 //    如果方法不是静态的,那么Invoke方法中第一个参数传值为 obj(上面那个被实例的对象)
    69         method1.Invoke(obj, parts);
    70         Console.WriteLine("调用的方法 " + this.strMetName[0] + ": " + x + " + " + y + " = " + parts[2]);
    71 
    72            int sum1 = (int)method2.Invoke(obj, new object[] { x + 10, y + 10 });
    73            Console.WriteLine("调用的方法 " + this.strMetName[1] + ": " + (x + 10) + " + " + (y + 10) + " = " + sum1);
    74 
    75 
    76                 object[] temParts = new object[3];
    77                 temParts[0] = x + 20;
    78                 temParts[1] = y + 20;
    79                 method3.Invoke(null, temParts);
    80                 Console.WriteLine("调用的方法 " + this.strMetName[2] + ": " + temParts[0] + " + " + temParts[1] + " = " + temParts[2]);
    81             }
    82         }
    83     }
    84 }

    在Main 函数中可以输入以下代码:

     1   using System;
     2 using System.Collections.Generic;
     3 using System.Text;
     4 using System.Windows.Forms;
     5 namespace ReflectionLesson
     6 {
     7     class Program
     8     {
     9         static void Main(string[] args)
    10         {
    11             string dllname = "RefDll";
    12             string claname ="RefTest";
    13             string[] metname = new string[]{"TestSum","TestSumTwo","TestSumThree"};
    14             ReflectionLesson refl = new ReflectionLesson(dllname, claname, metname);
    15             refl.ReflectionTest(100,200);
    16         }
    17     }
    18 }

    好了。现在可以跑一下如何调用的了,大家可以设置在调试模式下进行阅读代码。

    =========================================================================

    反射的作用: 1. 可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型 2. 应用程序需要在运行时从某个特定的程序集中载入一个特定的类型,以便实现某个任务时可以用到反射。 3. 反射主要应用与类库,这些类库需要知道一个类型的定义,以便提供更多的功能。

    1 需要反射的DLL

     1 using System;
     2 namespace Webtest
     3 {
     4 public class ReflectTest
     5 {
     6 public ReflectTest(){}
     7 public string WriteString(string s)
     8 {
     9    return "欢迎您," + s;
    10 }
    11 //静态函数
    12 public static string WriteName(string s)
    13 {
    14 return "欢迎您光临," + s;
    15 }
    16 //不带参数的函数
    17 public string WriteNoPara()
    18 {
    19 return "您使用的是无参数方法";
    20 }
    21 }
    22 }

    应用于反射的例子-在ASPNET页面中加入以下函数:

     1 public void test1()
     2 {
     3 System.Reflection.Assembly ass;
     4 Type type ;
     5 object obj;
     6 try
     7 {
     8 ass = System.Reflection.Assembly.LoadFile(@"d:\TestReflect.dll");//要绝对路径
     9 type = ass.GetType("Webtest.ReflectTest");//必须使用 名称空间+类名称
    10 System.Reflection.MethodInfo method = type.GetMethod("WriteString");//方法的名称
    11 obj = ass.CreateInstance("Webtest.ReflectTest");//必须使用名称空间+类名称
    12 string s = (string)method.Invoke(obj,new string[]{"jianglijun"}); // 实例方法的调用
    13 或:string s = (string)method.Invoke(obj,Object[] parametors = new Object[]{"param"}); 
    14 Response.Write(s+"<br>");
    15 method = type.GetMethod("WriteName");//方法的名称
    16 s = (string)method.Invoke(null,new string[]{"jianglijun"}); // 静态方法的调用
    17 Response.Write(s+"<br>");
    18 
    19 method = type.GetMethod("WriteNoPara");//无参数的实例方法
    20 s = (string)method.Invoke(obj,null);
    21 Response.Write(s+"<br>");
    22 method = null;
    23 }
    24 catch(Exception ex)
    25 {
    26 Response.Write(ex+"<br>");
    27 }
    28 finally
    29 {
    30 ass = null;
    31 type = null;
    32 obj = null;
    33 }
    34 } 
  • 相关阅读:
    cocos2d-x笔记5: 通过jni实现C++调用Java
    cocos2d-x笔记4: TextField不能删除内容,以及我的解决办法。。。
    C++ 11 笔记 (六) : 随机数
    C++ 11 笔记 (五) : std::thread
    C++ 11 笔记 (四) : std::bind
    C++ 11 笔记 (三) : auto
    C++ 11 笔记 (二) : for循环
    要做的题目
    【C补充】结构体的内存分配,匈牙利命名法
    【C补充】文件操作
  • 原文地址:https://www.cnblogs.com/lyghost/p/2581947.html
Copyright © 2011-2022 走看看