定义的接口:
namespace IProgramShut
{
public interface IShut
{
///
/// 操作名称
///
string OperatorName
{
get;
}
///
/// 操作方法
///
///
///
///
///
TResult Operator(T t);
}
}
namespace ProgramShutDown
{
public class ProgramShutDown :IShut
{
///
/// 显示“关机”字样
///
public string OperatorName
{
get
{
return "关机";
}
}
///
/// 关机操作
///
///
///
///
///
public TResult Operator(T t)
{
this.ShutDown(t.ToString());
return default(TResult);
}
///
/// 执行关机
///
///
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;
}
}
}
}
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的具体类型,
其中
泛型方法在接口中的声明如下:
TResult Operator(T t);
MethodInfo 类中的 MakeGenericMethod方法在NET中定义如下
//
// 摘要:
// 用类型数组的元素替代当前泛型方法定义的类型参数,并返回表示结果构造方法的 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方法,
或者是派生类中特有的定义的方法,这个例子只是凑巧了。
另外做个标记:
通过反射获取泛型类型的具体类型的方法是通过:
Type类的MakeGenericType方法来获取
该方法在NET中的定义如下
//
// 摘要:
// 替代由当前泛型类型定义的类型参数组成的类型数组的元素,并返回表示结果构造类型的 System.Type 对象。
//
// 参数:
// typeArguments:
// 将代替当前泛型类型的类型参数的类型数组。
//
// 返回结果:
// System.Type 表示的构造类型通过以下方式形成:用 typeArguments 的元素取代当前泛型类型的类型参数。
//
// 异常:
// System.InvalidOperationException:
// 当前类型不表示泛型类型定义。 即,System.Type.IsGenericTypeDefinition 返回 false。
//
// System.ArgumentNullException:
// typeArguments 为 null。 - 或 - typeArguments 的所有元素均为 null。
//
// System.ArgumentException:
// typeArguments 中元素的个数不等于当前泛型类型定义中类型参数的个数。 - 或 - typeArguments 的所有元素都不满足为当前泛型类型的对应类型参数指定的约束。
// - 或 - typeArguments包含元素,它是一个指针类型 (System.Type.IsPointer返回true),by-ref 类型
// (System.Type.IsByRef返回true),或 System.Void。
//
// System.NotSupportedException:
// 基类不支持所调用的方法。 派生类必须提供实现。
public virtual Type MakeGenericType(params Type[] typeArguments);
Type t = tsi.Tag as Type;
t.MakeGenericType(new object[]{typeof(int),typeof(string),..,..,..}) ;