65.9K
CodeProject 正在变化。 阅读更多。
Home

使用反射加载程序集并调用其中的静态方法

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.43/5 (5投票s)

2010年5月14日

CPOL

2分钟阅读

viewsIcon

52216

downloadIcon

857

使用反射在运行时调用程序集中的静态方法。

snapshot.png

引言

在本文中,我将展示如何在运行时使用反射加载程序集,并从中调用静态方法。

背景

反射是微软一项非凡的功能。在开始之前,我们必须了解一些关于程序集的非常重要的概念。程序集是.NET Framework的构建块。程序集是构建在一起工作的一组类型和资源,形成一个逻辑功能单元。

程序集包含模块,模块包含类型,类型包含成员。使用反射,我们可以创建类型的实例,可以调用类型的的方法,或者访问它的字段和属性。对于本教程,以上陈述就足够了。有关详细信息,请点击此处

使用代码

本教程包含两个项目

  1. 实用工具(类库)
  2. LoadAssembly(将使用反射加载实用工具的应用程序)

实用工具类库包含两种方法

  • Encrypt(接收一个字符串作为输入,并返回加密后的字符串作为输出)
  • Decrypt(接收一个加密后的字符串作为输入,并返回原始字符串)

我不会讨论实用工具代码,因为它不需要。实用工具代码如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Security.Cryptography;

namespace Utility
{
    public static class Cryptography
    {
        /// <summary>
        /// Author : Syed Fasih-ud-Din
        /// Dated : 15, March 2009  @  12:10
        /// Description : Decrypts Encrypted Text to Original Message
        /// </summary>
        /// <param name="EncryptedText">Encrypted string</param>
        /// <returns></returns>
        public static string Decrypt(this string EncryptedText)
        {
            byte[] bytes = Encoding.UTF8.GetBytes("LcB!ZLtd");
            byte[] rgbIV = Encoding.UTF8.GetBytes("!nforM@#");
            byte[] buffer = Convert.FromBase64String(EncryptedText);
            MemoryStream stream = new MemoryStream();
            try
            {
                DES des = new DESCryptoServiceProvider();
                CryptoStream stream2 = new CryptoStream(stream, 
                   des.CreateDecryptor(bytes, rgbIV), CryptoStreamMode.Write);
                stream2.Write(buffer, 0, buffer.Length);
                stream2.FlushFinalBlock();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }



            return Encoding.UTF8.GetString(stream.ToArray());
        }

        /// <summary>
        /// Author : Syed Fasih-ud-Din
        /// Dated : 15, March 2009  @  12:10
        /// Description : Encrypts Plain Text to Unreadable Form
        /// </summary>
        /// <param name="PlainText">Plain Text intended to Encrypt</param>
        /// <returns></returns>
        public static string Encrypt(this string PlainText)
        {
            byte[] bytes = Encoding.UTF8.GetBytes("LcB!ZLtd");
            byte[] rgbIV = Encoding.UTF8.GetBytes("!nforM@#");
            byte[] buffer = Encoding.UTF8.GetBytes(PlainText);
            MemoryStream stream = new MemoryStream();
            
            try
            {
                DES des = new DESCryptoServiceProvider();
                CryptoStream stream2 = new CryptoStream(stream, 
                   des.CreateEncryptor(bytes, rgbIV), CryptoStreamMode.Write);
                stream2.Write(buffer, 0, buffer.Length);
                stream2.FlushFinalBlock();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }


            return Convert.ToBase64String(stream.ToArray());
        }
    }
}

LoadAssembly

LoadAssembly项目将使用反射加载程序集,并调用这些方法。带有说明的代码如下。

将在应用程序中使用的变量是

// Will be holding the Types in the Assembly
Type[] TypesInAssembly = null;
// Will hold the Fully Qualified Name of the Assembly i.e. Namespace.Class
string AssemblyName = string.Empty;
// Will be holding the Full path of the Assembly
string AssemblyPath = string.Empty;
// Will hold the Path of the Currently Executing Assembly
// i.e. the Project EXE filr
string ExecutingAssemblyPath = string.Empty;
// These will hold the results of Encryption
// and Decryption from the loadedAssembly
object Result, DecryptedResult = null;

窗体加载

在窗体加载时,应用程序将加载Utility.dll,然后按钮事件将使用它来调用方法。窗体加载事件代码如下所示

//Getting Application Startup Path
ExecutingAssemblyPath = Application.StartupPath;

//Getting the Exact Directory where the application is running
ExecutingAssemblyPath = 
   System.IO.Path.GetDirectoryName(ExecutingAssemblyPath);

//Creating Full Path of Assembly
AssemblyPath = ExecutingAssemblyPath + "\\" + 
  ConfigurationManager.AppSettings["Location"].ToString() + 
  ConfigurationManager.AppSettings["Assembly"].ToString();

//Loading An Assembly From desired path
System.Reflection.Assembly MyAssembly = 
       System.Reflection.Assembly.LoadFrom(AssemblyPath);

//Getting Assembly Types (i.e. classes) here we have only 1 class
TypesInAssembly = MyAssembly.GetTypes();

//Creating Full Name of Assembly i.e. Namespace.ClassName
AssemblyName = TypesInAssembly[0].Namespace + "." + TypesInAssembly[0].Name;

//Getting Methods in Assembly Types
System.Reflection.MethodInfo[] MethodsCollection = TypesInAssembly[0].GetMethods();

调用方法

在进行调用之前,您必须了解如何调用静态方法。对于要调用的静态方法,有一个名为“target”的参数。如果您正在调用静态方法,则将此参数留空,框架将忽略它。如果您的方法不是静态的,那么您必须提供类的实例,并且该实例将通过CreateInstance方法创建。在我们的例子中,我们正在调用一个静态方法。

以下是将调用Utility.dll成员方法的按钮事件

private void bttnEncrypt_Click(object sender, EventArgs e)
{
    try
    {
        //Invoke Loaded Assembly Method
        Result = TypesInAssembly[0].InvokeMember("Encrypt", 
           System.Reflection.BindingFlags.InvokeMethod, System.Type.DefaultBinder, 
           "", new object[] { txtMessage.Text });
        txtEcnryptedMessage.Text = Result.ToString();
    }
    catch (Exception ex)
    {
       MessageBox.Show(ex.Message);
    }
}
private void bttnDecrypt_Click(object sender, EventArgs e)
{
    try
    {
        //Invoke Loaded Assembly Method
        DecryptedResult = TypesInAssembly[0].InvokeMember("Decrypt", 
            System.Reflection.BindingFlags.InvokeMethod, System.Type.DefaultBinder, 
            "", new object[] { txtEcnryptedMessage.Text });
        MessageBox.Show(DecryptedResult.ToString());
    }
    catch (Exception ex)
    {

          MessageBox.Show(ex.Message);
    }
}
© . All rights reserved.