代码改变世界

反射学习笔记之动态创建对象和调用方法

2010-02-24 21:14  爱研究源码的javaer  阅读(630)  评论(0编辑  收藏  举报

动态加载和静态引用的程序集并不是同一个Assembly了。事实上,在.Net中,同一个应用程序域并不允许同时加载两个相同的Assembly。即使加载了,也会认为是两个不同的程序集。如果要同时加载两个,则必须在不同的应用程序域中。可以通过AppDomain创建一个新的应用程序域,在其中动态加载;而原来的程序域则静态添加引用。此时将会认为是同一个程序集。

猜测是如此。我需要测试。想到我最近作的Remoting。服务器端和客户端正是两个不同的应用程序域。于是我在服务器端通过Activator.CreateInstance()动态创建对象,返回object类型。
然后再客户端静态添加该对象的引用。(我在本地机上试验,所以服务器端和客户端加载的程序集完全一样,包括路径都相同)然后再客户端通过Activator.GetObject()获得服务器端动态创建的对象,再显示进行强制转换。果然,使正确的。

转自:http://www.cnblogs.com/wayfarer/archive/2004/07/20/25968.html

 

 

使用无参数构造函数创建对象

System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();

Object obj = asm.CreateInstance("ReflectorDemo.Calculator", true);//true 说明是不是大小写无关(Ignore Case)。

 System.Runtime.Remoting.ObjectHandle handler = Activator.CreateInstance(null, "ReflectorDemo.Calculator");//null为当前程序集

 Object obj = handler.Unwrap();

 

使用有参数构造函数创建对象

 System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();

            Object[] parameters = new Object[2];

            parameters[0] = 3;

            parameters[1] = 5;

            Object obj = asm.CreateInstance("ReflectorDemo.Calculator", true, System.Reflection.BindingFlags.Default, null, parameters, null, null);

 

 // System.Runtime.Remoting.ObjectHandle oh = AppDomain.CurrentDomain.CreateInstance(System.Reflection.Assembly.GetExecutingAssembly().FullName, controlName);

                    //_currentControl = (Control)oh.Unwrap();

                    //System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();

                    //Object obj = asm.CreateInstance("NavigateControl.NavigatePanel", true);

                    //System.Runtime.Remoting.ObjectHandle handler = Activator.CreateInstance(null, "NavigateControl.NavigatePanel");//null为当前程序集

                    //Object obj = handler.Unwrap();

                    //System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();

                    //Object obj = asm.CreateInstance("NavigateControl.NavigatePanel",true, System.Reflection.BindingFlags.Default, null,null, null, null);

                    Type t = typeof(NavigateControl.NavigatePanel);

                    Object obj = Activator.CreateInstance(t);

 

 

 System.Reflection.Assembly asm = System.Reflection.Assembly.Load("NavigateControl");

                    Object obj = asm.CreateInstance("NavigateControl.NavigatePanel");


 

 

 

1.使用InvokeMember调用方法

 Type t = typeof(ReflectorDemo.Calculator);//Calculator是类

            int result = (int)t.InvokeMember("Add", System.Reflection.BindingFlags.InvokeMethod, null, obj, null);

            Console.WriteLine(String.Format("The result is {0}", result));

在InvokeMember方法中,第一个参数说明了想要调用的方法名称;第二个参数说明是调用方法(因为InvokeMember的功能非常强大,不光是可以调用方法,还可以获取/设置 属性、字段等。此枚举的详情可参看Part.2或者MSDN);第三个参数是Binder,null说明使用默认的Binder;第四个参数说明是在这个对象上(obj是Calculator类型的实例)进行调用;最后一个参数是数组类型,表示的是方法所接受的参数。

 

我们在看一下对于静态方法应该如何调用:

Object[] parameters2 = new Object[2];
parameters2[0] = 6;
parameters2[1] = 9;
t.InvokeMember("Add", BindingFlags.InvokeMethod, null, typeof(Calculator), parameters2);

输出:
Invoke Static Method:
[Add]: 6 plus 9 equals to 15

 

 使用MethodInfo.Invoke调用方法

//Type t = typeof(ReflectorDemo.Calculator);

            //System.Reflection.MethodInfo mi = t.GetMethod("Add", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);

            //int result = (int)mi.Invoke(obj, null);

 

使用MethodInfo调用静态方法

 Type t = typeof(ReflectorDemo.Calculator);

            Object[] parameters2 = new Object[2];

            parameters2[0] = 6;

            parameters2[1] = 9;

            System.Reflection.MethodInfo mi = t.GetMethod("Add", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);

           //int result = (int)mi.Invoke(null, parameters2);

            // int result  = (int)mi.Invoke(t, parameters2); //也可以这样