前几天,在编写程序时,遇到需要利用反射技术动态执行方法调用的需求,调用过程中传递引用类型参数后,值不能正常返回,具体参考下面网址:
google了很久,没有这方面资料。在这里感谢
“南疯”,看了
从而解决了我的问题,关于反射调用方法时传递应用类型参数的知识,南疯那篇文章写介绍很多了,现在把我在解决过程的想法写出来,我们首先从下面这段代码进行分析(下面的代码已经编译通过了):
namespace
App
{
public class A
{
public void setValue( int num,ref DataTable _tb)
{
num = 5;
_tb.Columns.Add("temp1");
}
public void setValue1(out string s,out DataTable _tb)
{
s = "temp2";
_tb = new DataTable();
_tb.Columns.Add("temp2");
}
}
class Test
{
[STAThread]
static void Main(string[] args)
{
int num = 0;
string s = "Reflection";
DataTable tb = new DataTable();
Type _type = typeof(A);
object _o = Activator.CreateInstance(_type);
// //section 1
object[] param = new object[2];
param[0] = s;
param[1] = tb;
Console.WriteLine(num);
Console.WriteLine(s);
Console.WriteLine(tb.Columns.Count+"/n");
ParameterModifier[] paramMods = new ParameterModifier[1];
paramMods[0] = new ParameterModifier(2);
paramMods[0][0] = true;
paramMods[0][1] = true;
_type.InvokeMember("setValue",BindingFlags.Default|BindingFlags.InvokeMethod,
null,_o,param,paramMods,null,null);
//section 2
Console.WriteLine(num);
Console.WriteLine(param[0]);
Console.WriteLine(((DataTable)param[1]).Columns.Count);
//section3
//Console.WriteLine(tb.Columns.Count);
}
}
}
{
public class A
{
public void setValue( int num,ref DataTable _tb)
{
num = 5;
_tb.Columns.Add("temp1");
}
public void setValue1(out string s,out DataTable _tb)
{
s = "temp2";
_tb = new DataTable();
_tb.Columns.Add("temp2");
}
}
class Test
{
[STAThread]
static void Main(string[] args)
{
int num = 0;
string s = "Reflection";
DataTable tb = new DataTable();
Type _type = typeof(A);
object _o = Activator.CreateInstance(_type);
// //section 1
object[] param = new object[2];
param[0] = s;
param[1] = tb;
Console.WriteLine(num);
Console.WriteLine(s);
Console.WriteLine(tb.Columns.Count+"/n");
ParameterModifier[] paramMods = new ParameterModifier[1];
paramMods[0] = new ParameterModifier(2);
paramMods[0][0] = true;
paramMods[0][1] = true;
_type.InvokeMember("setValue",BindingFlags.Default|BindingFlags.InvokeMethod,
null,_o,param,paramMods,null,null);
//section 2
Console.WriteLine(num);
Console.WriteLine(param[0]);
Console.WriteLine(((DataTable)param[1]).Columns.Count);
//section3
//Console.WriteLine(tb.Columns.Count);
}
}
}
分析:
1、
从上面的代码,我们声明了一个类
A
,同时类里面声明了重载函数
setValue
,主要是演示反射具有自动匹配参数类型相同的函数。
2、
在主函数中,我们关注
section1
、
section2
和
section3
三部分:
section1
主要是当我们传不同的参数,验证反射将会调用其匹配的函数。如上面的代码
Param[0]
传的是
s
,反射就会自动匹配调用第二个函数,如果给
param[0]
传入
num
,那反射就自动调用
A
类中的第一个函数,这可能是。
Net
中的类型安全的作用吧,但如果是使用
MethodInfo
中
Invoke
就不会自动匹配,不知道为什么?程序中
section2
下面的代码主要是验证使用反射技术调用需要传入引用类型的参数,引用类型参数值前后的变化;
section3
部分是一个容易忽视的地方,开始我也没注意,当我传入
ref
类型参数,
param[1]
和
tb
中的引用对象是一样的,可如果传入
out
类型参数时,
param[1]
和
tb
中引用的对象就不一样,不知道为什么会出现这种差别?所有如果需要取回
out
类型的参数的值时,就必须使用
para[1]
的值
3、
在使用反射技术要动态调用引用类型的参数时,在上面的参数
param[1]
必须初始化,不知道为什么?如果我们使用
MethodInfo
中
invoke
来调用传引用类型的参数时,如果含有重载函数时,尤其是传含有数据对象(
DataTable
或者
DataSet
),要找到匹配的函数特别繁琐。得到返回的值时,也必须使用传入参数数组中的对象,而不能使用函数中的变量。
以上就是我的一些心得,现在返过来想想,早期不能得到引用类型参数的返回值,主要就是忽视
section3
部分。