在網上查找了不少的資料,可以說大同小異,概念性的東西網上一搜一堆,
今天把反射的東西整理了一下,供大家使用,我保證我這裡是最全面的東西,當然也是基礎的東西,
在學好了這一切的基礎上,大家可以學習反射的具體插件等應用,老鳥就不用看了.
首先我們建立一個類庫,将它生成為helloworld.dll,
using system;
namespace webtest
{
public interface interface1
{
int add();
}
public class reflecttest:interface1
...
}
然後,建立再建立一個項目引入該helloworld.dll,
using system.threading;
using system.reflection;
class test
{
delegate string testdelegate(string value,int value1);
static void main()
{
//assembly t = assembly.loadfrom("helloworld.dll"); 與下面相同的效果
assembly t = assembly.load("helloworld");
//**********************************************************************
foreach (type aaa in t.gettypes())
{
//console.write(aaa.name); //顯示該dll下所有的類
}
//**********************************************************************
module[] modules = t.getmodules();
foreach (module module in modules)
{
//console.writeline("module name:" + module.name);//顯示子產品的名字本例為"helloworld.dll"
type a = typeof(webtest.reflecttest);//得到具體的類的類型,和下面一個效果
//type a = t.gettype("webtest.reflecttest");//
//console.write(a.name);
string[] bb ={ "aaaa", "bbbbb" };
object obj = activator.createinstance(a,bb); //建立該類的執行個體,後面的bb為有參構造函數的參數
//object obj = t.createinstance("webtest.reflecttest");//與上面方法相同
//**********************************************************************
methodinfo[] miarr = a.getmethods();
foreach (methodinfo mi0 in miarr)
//console.write(mi0.name); //顯示所有的共有方法
}
methodinfo mi = a.getmethod("writestring");//顯示具體的方法
object[] aa={"使用的是帶有參數的非靜态方法",2};
string s = (string)mi.invoke(obj,aa); //帶參數方法的調用
methodinfo mi1 = a.getmethod("writename");
string[] aa1 ={"使用的是靜态方法"};
string s1 = (string)mi1.invoke(null, aa1); //靜态方法的調用
methodinfo mi2 = a.getmethod("writenopara");
string s2 = (string)mi2.invoke(obj, null); //不帶參數的方法調用
methodinfo mi3 = a.getmethod("writeprivate",bindingflags.instance | bindingflags.nonpublic);
string s3 = (string)mi3.invoke(obj, null); //私有類型方法調用
//console.write(s3);
propertyinfo[] piarr = a.getproperties(bindingflags.instance | bindingflags.nonpublic | bindingflags.public);
foreach (propertyinfo pi in piarr)
//console.write(pi.name); //顯示所有的屬性
propertyinfo pi1=a.getproperty("writea");
//pi1.setvalue(obj, "writea", null);
//console.write(pi1.getvalue(obj,null));
propertyinfo pi2 = a.getproperty("writeb", bindingflags.instance | bindingflags.nonpublic | bindingflags.public);
pi2.setvalue(obj, "writeb", null);
//console.write(pi2.getvalue(obj, null));
fieldinfo fi1 = a.getfield("write");
//console.write(fi1.getvalue(obj));
constructorinfo[] ci1 = a.getconstructors();
foreach (constructorinfo ci in ci1)
//console.write(ci.tostring()); //獲得構造函數的形式
constructorinfo asci = a.getconstructor(new type[] { typeof(string), typeof(string) });
//console.write(asci.tostring());
webtest.interface1 obj1 = (webtest.interface1)t.createinstance("webtest.reflecttest");
webtest.reflecttest obj2 = (webtest.reflecttest)t.createinstance("webtest.reflecttest");
//console.write(obj1.add());典型的工廠模式
foreach (type tt in t.gettypes())
if (tt.getinterface("interface1")!=null)
{
webtest.interface1 obj3 = (webtest.interface1)activator.createinstance(a);
//console.write(obj3.add());
}
testdelegate method = (testdelegate)delegate.createdelegate(typeof(testdelegate), obj, "writestring");
//動态建立委托的簡單例子
//console.write(method("str1", 2));
constructorinfo asci1 = a.getconstructor(new type[0]);
webtest.reflecttest obj5 = (webtest.reflecttest)asci1.invoke(null);
//通過無參構造函數執行個體化的方法
//console.write(obj5.writea);
constructorinfo asci2 = a.getconstructor(new type[] { typeof(string), typeof(string) });
//通過有參構造函數執行個體化的方法
webtest.reflecttest obj6 = (webtest.reflecttest)asci2.invoke(bb);
console.write(obj6.writea);
console.read();
}
在這裡我把我們常用的方法,屬性,等全部整理了出來,大家不要嫌棄亂,靜下心來,自己按照我的分隔一部分一部分的來,保證你對反射的學習,會事半功倍.當然有關于其方法我會繼續補充,想了這麼些就先寫下來吧.
在.net的reflection中,constructorinfo和methodinfo都是從methodbase直接繼承而來的.
methodinfo的invoke函數使用很簡單,就是直接
methodinfo.invoke(object target,object[]
parameters);
但是constructorinfo的invoke函數有一點不一樣.
同methodinfo,constructorinfo的invoke也有這種形式的重載...
constructorinfo.invoke(object target ,object[]
這個invoke用在調用父類的構造函數的時,也就是對已有的一個對象,去調用他的構造函數.即:
class father{
public father(...){}
class son :
father{
public
son(...):base(...){}
son的構造函數的il代碼中,就會有相當于如下的函數的調用:
constructorinfo.invoke( this,
//具體的代碼可以參考aop.net中proxyfactory的aopbasehandler.cs中的invoke函數.
通過這種方式,完成子類son對其父類father的構造函數的調用.
constructorinfo.invoke還有一種形式:
object constructorinfo.invoke( object[]
這個就是用來生成一個新的對象用的.即:
object
target = constructorinfo.invoke(parameters);
和
object target = new
son(parameters);
是一樣的...
通過這個函數可以得到一個新的對象.和new是一樣的效果.
使用這個的時候可能要注意一下:p