如何通过反射调用类中的<泛型>方法

 我来答
huanglenzhi
2017-12-05 · 知道合伙人数码行家
huanglenzhi
知道合伙人数码行家
采纳数:117538 获赞数:517196
长期从事计算机组装,维护,网络组建及管理。对计算机硬件、操作系统安装、典型网络设备具有详细认知。

向TA提问 私信TA
展开全部
定义的接口:
[csharp] view plain copy

namespace IProgramShut

{

public interface IShut

{

/// <summary>

/// 操作名称

/// </summary>

string OperatorName

{

get;

}

/// <summary>

/// 操作方法

/// </summary>

/// <typeparam name="T"><peparam>

/// <typeparam name="TResult"><peparam>

/// <param name="t"></param>

/// <returns></returns>

TResult Operator<T, TResult>(T t);

}

}

派生自接口的派生类:
[csharp] view plain copy

namespace ProgramShutDown

{

public class ProgramShutDown :IShut

{

/// <summary>

/// 显示“关机”字样

/// </summary>

public string OperatorName

{

get

{

return "关机";

}

}

/// <summary>

/// 关机操作

/// </summary>

/// <typeparam name="T"><peparam>

/// <typeparam name="TResult"><peparam>

/// <param name="t"></param>

/// <returns></returns>

public TResult Operator<T,TResult>(T t)

{

this.ShutDown(t.ToString());

return default(TResult);

}

/// <summary>

/// 执行关机

/// </summary>

/// <param name="second"></param>

public void ShutDown(string second)

{

Process process = new Process();

try

{

process.StartInfo.FileName = "cmd.exe";

process.StartInfo.UseShellExecute = false;

process.StartInfo.RedirectStandardInput = true;

process.StartInfo.RedirectStandardOutput = true;

process.StartInfo.RedirectStandardError = true;

process.StartInfo.CreateNoWindow = true;

process.Start();

process.StandardInput.WriteLine("shutdown -s -f -t " + second);

process.StandardInput.WriteLine("exit");

}

catch (Exception ex)

{

}

finally

{

process.Close();

process.Dispose();

process = null;

}

}

}

}

具体的调用方法:
[csharp] view plain copy

Type t = tsi.Tag as Type;

//1、获取指定方法名称的泛型方法

MethodInfo mi = t.GetMethod("Operator");

//2、创建一个对应泛型类型的非泛型反射方法

MethodInfo mi2 = mi.MakeGenericMethod(new Type[] { typeof(int), typeof(int) });

object o = Activator.CreateInstance(t);

mi2.Invoke(o, new object[] { 3000 });

其中tsi是一个ToolStripItem对象,我把通过反射获取到的需要被调用的类的类型存在了ToolStripItem.Tag中了, MethodInfo mi =t.GetMethod("Operator")通过方法名称获取到泛型方法的版本,然后在获取到的泛型方法MethodInfo mi的基础上,通过mi的MakeGenericMethod(new Type[] { typeof(int), typeof(int) })方法,创建一个非泛型版本,其中new Type[] { typeof(int), typeof(int)}是用来替换泛型类型 T,TResult的具体类型,其中泛型方法在接口中的声明如下:
[csharp] view plain copy

TResult Operator<T, TResult>(T t);

MethodInfo 类中的 MakeGenericMethod方法在NET中定义如下

[csharp] view plain copy

//

// 摘要:

// 用类型数组的元素替代当前泛型方法定义的类型参数,并返回表示结果构造方法的 System.Reflection.MethodInfo 对象。

//

// 参数:

// typeArguments:

// 要替换当前泛型方法定义的类型参数的类型数组。

//

// 返回结果:

// 一个 System.Reflection.MethodInfo 对象,表示通过将当前泛型方法定义的类型参数替换为 typeArguments 的元素生成的构造方法。

//

// 异常:

// System.InvalidOperationException:

// 当前 System.Reflection.MethodInfo 不表示泛型方法定义。 也就是说,System.Reflection.MethodInfo.IsGenericMethodDefinition

// 返回 false。

//

// System.ArgumentNullException:

// typeArguments 为 null。 - 或 - typeArguments 的所有元素均为 null。

//

// System.ArgumentException:

// typeArguments 中元素的数目与当前泛型方法定义的类型参数的数目不同。 - 或 - typeArguments 的某个元素不满足为当前泛型方法定义的相应类型参数指定的约束。

//

// System.NotSupportedException:

// 不支持此方法。

public virtual MethodInfo MakeGenericMethod(params Type[] typeArguments);

第一次尝试的时候是通过mi.Invoke直接调用的爆出了异常:无法绑定到目标方法,因其签名或安全透明度与委托类型的签名或安全透明度不兼容。后来查资料再是尝试,找到了另外的调用方式。做个记录。
再说一句:在这个例子中,想要调用的方法刚好是从接口中继承来的,public类型的方法,在通过反射调用泛型方法的时候已经获取到了对应类型的实例对象,原本可以直接通过实例对象调用对应的方法,但是不排除将来在实际使用的时候想要调用的是private方法,或者是派生类中特有的定义的方法,这个例子只是凑巧了。
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式