屋顶上的木帷幕

海鸥之所以追着渔船飞,是因为它们认为会有沙丁鱼抛向大海 - Eric Cantona, 1995
随笔 - 146, 评论 - 3168, 引用 - 56

导航

工具

关于


标签

每月存档

广告



访客

 

如果想复用别人写的.NET程序但手上只有一个编译过的EXE,那么方法之一是用Reflection(反射)。下面是一些例子,初次上手的人可以参考。

先假设我们要复用的第三方应用程序EXE是由下面的代码编译成的:

using System;
namespace MyNamespace
{
 public class MyApp
 {
  public MyNestedObject myNestedObject=null;
  public class MyNestedObject{
   public string name;
  }
  public enum FourSeasonsEnum{
   spring, summer, autumn, winter
  }
  public MyApp(){
  }
  public MyApp(MyNamespace.MyForm form){
  }
  public MyNestedObject Foo1(FourSeasonsEnum season){
   return this.myNestedObject;
  }
  public string Foo2(){
   return "";
  }
  static void Main(){
  }
 }
 public class MyForm
 {
  public MyForm(){
  }
 }
}

以下是一些直接引用时常见的调用如何用Reflection来改写:

1. 用不含参数的构造函数生成对象

直接引用时,代码是

MyNamespace.MyApp app=new MyNamespace.MyApp();

用Reflection来调用的话就需要这么写(记得using System.Reflection)

Assembly assem=Assembly.LoadFile(@"C:\Home\Workspace\MyNamespace\myapp.exe");
Type MyAppType=assem.GetType("MyNamespace.MyApp");
ConstructorInfo MyAppType_Constructor=MyAppType.GetConstructor(new Type[]{});
object app=MyAppType_Constructor.Invoke(new object[]{});

2. 用含参数的构造函数生成对象

直接引用时,代码是

MyNamespace.MyApp app=new MyNamespace.MyApp(new MyNamespace.MyForm());

用Reflection来调用的话就需要这么写

Assembly assem=Assembly.LoadFile(@"C:\Home\Workspace\MyNamespace\myapp.exe"); 
Type MyAppType=assem.GetType("MyNamespace.MyApp"); 
Type MyFormType=assem.GetType("MyNamespace.MyForm");
ConstructorInfo MyAppType_Constructor=MyAppType.GetConstructor(new Type[]{MyFormType});
ConstructorInfo MyFormType_Constructor=MyFormType.GetConstructor(new Type[]{});
object form=MyFormType_Constructor.Invoke(new object[]{});
object app=MyAppType_Constructor.Invoke(new object[]{form});

3. 调用对象的方法

直接引用时,代码是

MyNamespace.MyApp app=new MyNamespace.MyApp();
string str=app.Foo2();

用Reflection来调用的话就需要这么写

Assembly assem=Assembly.LoadFile(@"C:\Home\Workspace\MyNamespace\myapp.exe");
Type MyAppType=assem.GetType("MyNamespace.MyApp");
ConstructorInfo MyAppType_Constructor=MyAppType.GetConstructor(new Type[]{});
object app=MyAppType_Constructor.Invoke(new object[]{});
object str=MyAppType.GetMethod("Foo2").Invoke(app,new object[]{});

4. Set/Get成员变量

直接引用时,代码是

MyNamespace.MyApp app=new MyNamespace.MyApp();
MyNamespace.MyApp.MyNestedObject obj=app.myNestedObject;
MyNamespace.MyApp.MyNestedObject obj2=new MyNamespace.MyApp.MyNestedObject();
app.myNestedObject =obj2;

用Reflection来调用的话就需要这么写(注意,这里的MyNestedObject类是nested type,名字要用"MyNamespace.MyApp+MyNestedObject"而不是"MyNamespace.MyApp.MyNestedObject")

Assembly assem=Assembly.LoadFile(@"C:\Home\Workspace\MyNamespace\myapp.exe");
Type MyAppType=assem.GetType("MyNamespace.MyApp");
ConstructorInfo MyAppType_Constructor=MyAppType.GetConstructor(new Type[]{});
object app=MyAppType_Constructor.Invoke(new object[]{});
Type MyNestedObjectType=assem.GetType("MyNamespace.MyApp+MyNestedObject");
FieldInfo MyNestedObjField=MyAppType.GetField("myNestedObject");
object obj=MyNestedObjField.GetValue(app);
    
ConstructorInfo MyNestedObjectType_Constructor=MyNestedObjectType.GetConstructor(new Type[]{});
object obj2=MyNestedObjectType_Constructor.Invoke(new object[]{});
MyNestedObjField.SetValue(app,obj2);

5. 使用枚举类型

直接引用时,代码是

MyNamespace.MyApp app=new MyNamespace.MyApp();
MyNamespace.MyApp.MyNestedObject obj=app.Foo1(MyNamespace.MyApp.FourSeasonsEnum.spring);

用Reflection来调用的话就需要这么写

Assembly assem=Assembly.LoadFile(@"C:\Home\Workspace\MyNamespace\myapp.exe");
Type MyAppType=assem.GetType("MyNamespace.MyApp");
ConstructorInfo MyAppType_Constructor=MyAppType.GetConstructor(new Type[]{});
object app=MyAppType_Constructor.Invoke(new object[]{});
Type FourSeasonsEnumType=assem.GetType("MyNamespace.MyApp+FourSeasonsEnum");
Array FourSeasonsEnumValues=Enum.GetValues(FourSeasonsEnumType);
object SpringValue=FourSeasonsEnumValues.GetValue(0);
object result=MyAppType.GetMethod("Foo1").Invoke(app,new object[]{SpringValue});

---

最后,只要有可能,应该尽量不用Reflection,因为相比起直接调用,Reflection的性能相当差


随贴广告(测试期)
相关文章

打印 | 张贴于 2004-10-10 20:49:00 | Tag:Dot NET

留言反馈

re: 用反射调用别人的.NET程序里的类和方法 编辑
很奇怪,我用 "1. 用不含参数的构造函数生成对象" 里的方法得到了 object app, 我不能把它用 (MyApp)app 转成 Myapp,但是却可以用3里面的方法调用app里的方法,这是为什么呢?
2006-01-10 01:38:00 | [匿名用户:Savior]
re: 用反射调用别人的.NET程序里的类和方法 编辑
不错,我最近在自己编写实现反序列化(.net compact framework 不支持序列化),从xml中读取信息创建对象用到了文章中提及的,解决!
2005-08-13 13:35:00 | [匿名用户:JERRY]
re: 用反射调用别人的.NET程序里的类和方法 编辑
反射的重點 在於 能夠真正的latebind 在執行期間決定叫用的 物件 方法 讓程式人員能夠提供設定的空間
2005-04-25 17:08:00 | [匿名用户:I]
re: 用反射调用别人的.NET程序里的类和方法 编辑
.NET 动态调用不同版本的COM组件,就要用到,什么叫连可能都没有?
2005-03-25 10:11:00 | [匿名用户:111]
re: 用反射调用别人的.NET程序里的类和方法 编辑
留下来,等连可能都没有的时候用。
2004-10-13 10:05:00 | [匿名用户:wollaston]
re: 用反射调用别人的.NET程序里的类和方法 编辑
反射还是非常有用的,如调用private的函数,访问private的属性等等,这是其它方法办不到的。
2004-10-11 12:18:00 | [匿名用户:床上用品行业的B2B网站--中国寝具网]
re: 用反射调用别人的.NET程序里的类和方法 编辑
哎,和当年的IUnknown一样复杂,干嘛不用LateBind或者compiler-import呢,这个reflact的设计人员估计也是java出身的borland空降兵。。。
2004-10-10 21:52:00 | [匿名用户:bruise]
博客主人设置本博客不允许匿名用户发表言论,请登录后再试

Powered by: Joycode MVC Blogger System