開放原始碼的 .NET 反組譯工具 - ILSpy


ILSpy 的操作介面有點像 .NET Reflector,雖然功能比較少一點,但基本上還算夠用。就 open source 軟體而言,其實挺不錯的。如果不想花錢買 .NET Reflector,不妨試試 ILSpy。


[2012-01-04 更新]

用這段簡單的 LINQ 範例來比較 ILSpy 和 Reflector 反組譯成 C# 的差異:

        public void Linq1()
        {
            int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
 
            var lowNums =
                from n in numbers
                where n < 5
                select n;
 
            Console.WriteLine("Numbers < 5:");
            foreach (var x in lowNums)
            {
                Console.WriteLine(x);
            }
        }

使用 Reflector 反組譯的結果:


使用 ILSpy 反組譯的結果:

就這個例子而言,程式語法並沒有太大差異。不過,ILSpy 開發社群的部落格上有一篇文章,是 2011 年 4 月發表的,裡面提到:
We're now close to supporting all features in C# 3.0, the only major missing item is expression tree support. So LINQ queries currently decompile into query syntax only if they're compiled into delegates (LINQ-to-Objects, Parallel LINQ), not if they're compiled into expression trees (LINQ-to-SQL etc.).
所以,目前的 ILSpy 1.0 版尚未支援 expression tree。根據官網的說法,這部分將於 2.0 版實現。

8 則留言:

  1. 在我的文章Visual Basic for Reflection(http://blog.kkbruce.net/2011/09/visual-basic-reflection-2.html#.TwFlHflu6pQ)中有提到一套Telerik JustDecompile,目前是免費使用,功能不比 .NET Reflector,提供給你參考。

    回覆刪除
  2. 功能不比 .NET Reflector差 <-- 少了一個字

    回覆刪除
  3. 我小試了一下
    ILSpy反組譯後的內容與原程式碼相去較遠
    而.NET Reflector較接近
    尤其是程式碼中若包含Linq語句
    ILSpy反組譯後的結果幾乎沒有可讀性, 也無法編譯
    相較於這點, .NET Reflector表現則優異許多

    至於為什麼ILSpy反組譯Linq會讓人看不懂??
    因為它拆太細了, 拆到變成Expression Tree
    而非標準Linq表達式

    回覆刪除
  4. 感謝 Nicholas 的分享。我針對這部分做了點簡單的測試,並且補充在正文裡。看起來,ILSpy 是支援 LINQ 語法的,但目前並未支援 expression tree,我猜想這可能是你所碰到的狀況。

    回覆刪除
  5. 網誌管理員已經移除這則留言。

    回覆刪除
  6. 感謝Huanlin Tsai老師的指正!!
    經過我的實驗,果然如同老師所說,單純的Linq是不會有問題的

    不過秉持著追根究底的精神
    我還原了案發現場

    原本程式:
    private static void Main(string[] args)
    {
    var db = new TestDatabaseContext();

    var datas = db.People
    .Where(r => r.Name == "Angel")
    .Select(r => r.Name);
    }

    .NET Reflector:
    private static void Main(string[] args)
    {
    TestDatabaseContext db = new TestDatabaseContext();
    IQueryable datas = from r in db.People
    where r.Name == "Angel"
    select r.Name;
    }

    ILSpy:
    private static void Main(string[] args)
    {
    TestDatabaseContext db = new TestDatabaseContext();
    IQueryable arg_71_0 = db.People;
    ParameterExpression parameterExpression = Expression.Parameter(typeof(People), "r");
    IQueryable arg_B1_0 = arg_71_0.Where(Expression.Lambda>(Expression.Equal(Expression.Property(parameterExpression, (MethodInfo)MethodBase.GetMethodFromHandle(ldtoken(get_Name()))), Expression.Constant("Angel", typeof(string)), false, (MethodInfo)MethodBase.GetMethodFromHandle(ldtoken(op_Equality()))), new ParameterExpression[]
    {
    parameterExpression
    }));
    parameterExpression = Expression.Parameter(typeof(People), "r");
    IQueryable datas = arg_B1_0.Select(Expression.Lambda>(Expression.Property(parameterExpression, (MethodInfo)MethodBase.GetMethodFromHandle(ldtoken(get_Name()))), new ParameterExpression[]
    {
    parameterExpression
    }));
    }

    這是一段以EF存取DB的範例程式
    出現了我所說的情況
    所以我猜想也許是EF或是IQueryable造成的
    如果跟IQueryable有關
    說不定Linq to SQL也會有相同的問題(猜的)
    以上
    謝謝

    回覆刪除
  7. 我想原因大概就跟正文中最後補充的那段引用官網的文字有關:目前的 ILSpy v1.0 尚未支援 expression tree。由於有些 LINQ to EF 的語法會被 C# 編譯器編譯成 expression tree 的 statement,所以ILSpy 只是老實照翻,而沒有把它逆向轉回原本的簡易語法。這部分的語法支援據說會在 ILSpy v2.0 提供。多謝你的追根究柢 ^^

    回覆刪除

技術提供:Blogger.