奇技淫巧: Reflection存取內部/私有類別及子類別
0 |
以下是昨天偵察.NET 2.0版本問題時新學的黑暗技巧。
使用反組譯工具追查到FtpControlStream這個internal class,想呼叫其中的方法驗證問題所在:
問題來了,既然是內部/私有類別,以外部程式的角度就不可能大大方方地宣告
FtpControlStream ftpStm = new FtpControlStream();
輕鬆搞定,得透過Reflection技巧實現。
Reflection的第一步要取得型別(Type),而外部程式不認得內部/私有類別,不可能用typeof(FtpControlStream)方式取型別,需要繞點路。進一步,呼叫時的一個參數GetPathOption,其型別是一個私有列舉,算是內部類別中的子類別,又是一項新挑戰。
解說都寫在註解裡了,大家直接看Code吧!
using System;
using System.Net;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
//因為FtpControlStream是內部類別
//不可能用typeof(FtpControlStream)方式取得Type
//要先取得其所屬Assembly(System.dll),再GetType()
//先找到跟FtpControlStream在同一個Assembly的FtpWebRequest
//找到Assembly
var asm = typeof(FtpWebRequest).Assembly;
var fcsType = asm.GetType("System.Net.FtpControlStream");
Console.WriteLine(fcsType.FullName);
//接下來表演取得子類別GetPathOption
//直覺上大家會寫成System.Net.FtpControlStream.GetPathOption
Type gpoType = asm.GetType("System.Net.FtpControlStream.GetPathOption");
//結果會找不到
if (gpoType == null)
Console.WriteLine("取得GetPathOption失敗!");
//原來子類別在Type字串中是用+表示的啦
gpoType = asm.GetType("System.Net.FtpControlStream+GetPathOption");
Console.WriteLine(gpoType.FullName);
//同場加映,怎麼宣告內部/私有列舉?
//由於限定內部存取,無法用GetPathOption gpo = GetPathOption.Normal就搞定
//所以要透過Enum.Parse(參考: http://bit.ly/QAUvEf)
object gpo = Enum.Parse(gpoType, "Normal");
Console.WriteLine(gpo.ToString());
Console.Read();
}
}
}
Comments
Be the first to post a comment