以下是昨天偵察.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

Post a comment