通过反射创建对象

Assembly assembly = Assembly.LoadFile("程序集路径,不能是相对路径"); // 加载程序集(EXE 或 DLL)
object obj = assembly.CreateInstance("类的完全限定名(即包括命名空间)"); // 创建类的实例

若要反射当前项目中的类可以为:

Assembly assembly = Assembly.GetExecutingAssembly(); // 获取当前程序集
object obj = assembly.CreateInstance("类的完全限定名(即包括命名空间)"); // 创建类的实例,返回为 object 类型,需要强制类型转换

 

如果那些需要被反射的Form与FormMain在同一程序集中,可以用Activator类反射Form对象:

Form f = (Form)Activator.CreateInstance(Type.GetType(name));

然后

f.Visible = true;

f.Show(); // 非模态,或按模态方式显示 f.ShowDialog()

注意,name参数必须是要反射的Form对象的带命名空间的名称。

完整代码:

private void ShowWindowByName(string name)

        {

            Form f = (Form)Activator.CreateInstance(Type.GetType(name));

            f.Visible = true;

            f.Show();

        }

调用:

ShowWindowByName(this.GetType().Namespace+"."+"Form1");

ShowWindowByName(this.GetType().Namespace+"."+"Form2");

......



针对你的补充:

是呀,还是按照以往的方式,在Form1,Form2...上添加控件和事件处理方法。反射的意思是,根据现有的已经制作好的窗体的名字,在运行时动态地创建它的实例,然后Show出来。你可以试试看,先做一个Form1窗体,放上按钮什么的,然后再做FormMain窗体,添加一个按钮,然后在添加Click事件的处理方法,在这方法之中,加入上面的代码。

 

 

[c#美味] 使用反射动态创建实例并调用方法

 

在.Net 中,程序集(Assembly)中保存了元数据(MetaData)信息,因此就可以通过分析元数据来获取程序集中的内容,比如类,方法,属性等,这大大方便了在运行时去动态创建实例。

MSDN解释如下:

反射提供了封装程序集、模块和类型的对象(Type 类型)。可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性。如果代码中使用了属性,可以利用反射对它们进行访问。

主要用途:

  1. 动态加载DLL,实现插件机制。
  2. 实例化DLL中的类型。
  3. 执行后期绑定,访问在运行时创建的类型的方法。

 

今天我就介绍下后面的两个用途,其实最初的目的只是想根据配置文件中的值创建对应对象。

 

Dll

先上一段代码,这是要调用的ClassGreenerycn类,它被编译为DllDemo.dll。

using System;

namespace DllDemo
{
    public class ClassGreenerycn
    {
        public string Name { get; set; }

        public bool IsTest { get; set; }

        public void Hello()
        {
            Console.WriteLine(Name);
        }
    }
}

 

很简单的代码,就是一个类中有两个属性,Hello方法会向命令行中输出Name的名称。

 

使用反射创建Dll中的类实例并调用方法

现在再新建一个命令行的工程,该工程就一个用途,动态加载DllDemo.dll,然后实例化一个Name为Greenerycn,IsTest为True的对象,并调用Hello方法。

详细步骤如下:

1.引用反射的命名空间:

using System.Reflection;

2.动态加载Dll

动态加载Dll有3个函数:

public static Assembly Load(string assemblyString);
  • 该方法传入的是Dll的名字,该Dll必须位于全局缓存GAC中才行,不然会报“System.IO.FileLoadException: 未能加载文件或程序集”的异常。
public static Assembly LoadFile(string path);
  • 这个LoadFile最方便,参数就是dll的路径。
public static Assembly LoadFrom(string assemblyFile);
  • 这个方法也可以,参数同样是dll路径。

 

3.获取ClassGreenerycn类的类型

var type = asm.GetType("DllDemo.ClassGreenerycn");

注意,这里需要完整的类型名称,包括签名的命名空间。

4.创建该类型的实例

var instance = asm.CreateInstance("DllDemo.ClassGreenerycn");

5.设置属性

type.GetProperty("Name").SetValue(instance, "http://greenerycn.cnblogs.com", null);
type.GetProperty("IsTest").SetValue(instance, true, null);

6.获取Hello方法

var method = type.GetMethod("Hello");

7.调用Hello方法

method.Invoke(instance, null);

8.编译运行

reflaction_demo

完整的代码

using System.Reflection;

namespace ReflectionDllDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            var asm = Assembly.LoadFile(@"d:\3_code\DotNet\DllDemo\DllDemo\bin\Debug\DllDemo.dll");

            var type = asm.GetType("DllDemo.ClassGreenerycn");

            var instance = asm.CreateInstance("DllDemo.ClassGreenerycn");

            type.GetProperty("Name").SetValue(instance, "http://greenerycn.cnblogs.com", null);
            type.GetProperty("IsTest").SetValue(instance, true, null);

            var method = type.GetMethod("Hello");
            method.Invoke(instance, null);
        }
    }
}
posted @ 2013-09-15 11:22  长白山  阅读(508)  评论(0编辑  收藏  举报