.net установка - Альтернативы Open Source для рефлектора?




ilspy reflector (9)

Просто спросить, знает ли кто-нибудь об альтернативе с открытым исходным кодом для Reflector от RedGate? Мне интересно узнать, как работает инструмент, похожий на Reflector.

Обратите внимание: если вы знаете бесплатную альтернативу Reflector, но не с открытым исходным кодом, вы можете ответить на следующий связанный с этим вопрос:

Основная информация - Обновлено 11 мая 2011

Быстрый обзор различных проектов и инструментов с открытым исходным кодом, которые были предложены:

  1. Общая инфраструктура компилятора (CCI)
  2. Моно Сесил
  3. ILSpy
  4. dnSpy (fork ILSpy, проект выглядит более активным, чем оригинал)
  5. Редактор Dotnet IL (DILE)
  6. IL.View
  7. Monoflector ( более не действует по состоянию на апрель 2011 года)

Также могут быть интересны следующие ресурсы:

  • TypeView.cs
  • Заметки Джейсона Хейли о разборке .NET
  • Недавнее сообщение в блоге Adrian Bank, в котором излагается ряд альтернатив Reflector, включая несколько вариантов, не упомянутых ниже.
  • Подробное сообщение блога Марка Лихтенберга сравнивает несколько альтернатив с открытым исходным кодом (DILE, ILSpy и Mono Cecil с использованием MonoDevelop) с Reflector.

Answers

Другой заменой будет dotPeek . JetBrains объявила об этом как бесплатный инструмент. Вероятно, у него будет больше возможностей при использовании с их Resharper но даже при использовании в одиночку он работает очень хорошо.

Опыт пользователя больше похож на MSVS, чем на автономный дизассемблер. Мне нравится чтение кода больше, чем в Reflector. Ctrl + T подходит мне тоже лучше. Просто синхронизация дерева с областью кода может быть лучше.

В целом, он все еще находится в разработке, но очень хорошо используется.


Сегодня Telerik выпустила бета-версию своего инструмента декомпиляции JustDecompile . Закрытый источник, но бесплатный и выглядит многообещающим.


В настоящее время я работаю над дизассемблером / декомпилятором с открытым исходным кодом, называемым Assembly Analyzer. Он генерирует исходный код для методов, отображает метаданные и ресурсы сборки и позволяет вам просматривать зависимости.

Проект размещен на CodePlex => http://asmanalyzer.codeplex.com/


ILSpy работает!

Насколько я могу судить, он делает все, что сделал Reflector, и выглядит одинаково.


2 варианта, о которых я знаю.

Это не даст вам C #.


На самом деле, я уверен, что Reflector считается дизассемблером с некоторыми функциями декомпилятора. Disassembler, потому что он считывает байты из файла сборки и преобразует его на язык ассемблера (в этом случае ILasm). Функцию Decompiler, которую он предоставляет, анализируя IL в хорошо известные шаблоны (например, выражения и утверждения), которые затем переводятся на языки более высокого уровня, такие как C #, VB.Net и т. Д. Addin api for Reflector позволяет вам писать свой собственный переводчик языка, если вы хотите ... однако волшебство того, как он анализирует IL в деревьях выражений, - это тщательно охраняемая тайна.

Я бы рекомендовал взглянуть на любую из трех вещей, упомянутых выше, если вы хотите понять, как работают дисассемблеры IL: Dile, CCI и Mono - все это хорошие источники для этого материала.

Я также очень рекомендую получить спецификацию Ecma 335 и книгу Сержа Лидина.


В инструменте Reflector используется Reflection. - По-видимому, это неверно.

Вы попросили две вещи - код, который показывает, что делает отражатель, а также альтернатива рефлектору.

Вот пример, значительно упрощенный от того, что делает Reflector, но он показывает технику отражения: TypeView.cs

У меня нет предложения об замене рефлектора с открытым исходным кодом.


Ну, Reflector сам является сборкой .NET, поэтому вы можете открыть Reflector.exe в Reflector, чтобы узнать, как он построен.


Что касается вызова одного метода:

  • Прямой вызов не может быть избит по скорости.
  • Использование Expression API во всем мире аналогично использованию Reflection.Emit или Delegate.CreateDelegate скорости (могут быть измерены небольшие различия, так как всегда оптимизация скорости без измерений и целей бесполезна).

    Все они генерируют IL, и в какой-то момент структура будет скомпилировать его с собственным кодом. Но вы по-прежнему оплачиваете стоимость одного уровня косвенности для вызова делегата и одного вызова метода внутри вашего делегата.

    Выражение API более ограничено, но на порядок проще использовать, поскольку оно не требует изучения IL.

  • Продолжительность выполнения динамического языка, используемая напрямую или через dynamic ключевое слово C # 4, добавляет немного накладных расходов, но остается рядом с испускающим кодом, поскольку он кэширует большинство проверок, связанных с типами параметров, доступом и остальными.

    Когда используется ключевое слово dynamic он также получает самый чистый синтаксис, поскольку он выглядит как обычный вызов метода. Но если вы используете динамический, вы ограничены вызовами методов, в то время как библиотека может делать намного больше (см. IronPython )

  • System.Reflection.MethodInfo.Invoke работает медленно: в дополнение к тому, что другим методам необходимо проверить права доступа, проверять аргументы count, type, ... на MethodInfo каждый раз, когда вы вызываете метод.

Джон Скит также получает некоторые хорошие моменты в этом ответе: Delegate.CreateDelegate vs DynamicMethod vs Expression

Некоторые образцы, то же самое делали по-разному.

Вы уже можете видеть из подсчета строк и сложности, какие решения просты в обслуживании и которых следует избегать с точки зрения долгосрочного обслуживания.

Большинство примеров бессмысленны, но они демонстрируют основные классы генерации кода / синтаксиса C #, для получения дополнительной информации всегда есть MSDN

PS: Дамп - это метод LINQPad .

public class Foo
{
    public string Bar(int value) { return value.ToString(); }
}

void Main()
{
    object foo = new Foo();

    // We have an instance of something and want to call a method with this signature on it :
    // public string Bar(int value);

    Console.WriteLine("Cast and Direct method call");
    {
        var result = ((Foo)foo).Bar(42);
        result.Dump();
    }
    Console.WriteLine("Create a lambda closing on the local scope.");
    {
        // Useless but i'll do it at the end by manual il generation

        Func<int, string> func = i => ((Foo)foo).Bar(i);
        var result = func(42);
        result.Dump();
    }
    Console.WriteLine("Using MethodInfo.Invoke");
    {
        var method = foo.GetType().GetMethod("Bar");
        var result = (string)method.Invoke(foo, new object[] { 42 });
        result.Dump();
    }
    Console.WriteLine("Using the dynamic keyword");
    {
        var dynamicFoo = (dynamic)foo;
        var result = (string)dynamicFoo.Bar(42);
        result.Dump();
    }
    Console.WriteLine("Using CreateDelegate");
    {
        var method = foo.GetType().GetMethod("Bar");
        var func = (Func<int, string>)Delegate.CreateDelegate(typeof(Func<int, string>), foo, method);
        var result = func(42);
        result.Dump();
    }
    Console.WriteLine("Create an expression and compile it to call the delegate on one instance.");
    {
        var method = foo.GetType().GetMethod("Bar");
        var thisParam = Expression.Constant(foo);
        var valueParam = Expression.Parameter(typeof(int), "value");
        var call = Expression.Call(thisParam, method, valueParam);
        var lambda = Expression.Lambda<Func<int, string>>(call, valueParam);
        var func = lambda.Compile();
        var result = func(42);
        result.Dump();
    }
    Console.WriteLine("Create an expression and compile it to a delegate that could be called on any instance.");
    {
        // Note that in this case "Foo" must be known at compile time, obviously in this case you want
        // to do more than call a method, otherwise just call it !
        var type = foo.GetType();
        var method = type.GetMethod("Bar");
        var thisParam = Expression.Parameter(type, "this");
        var valueParam = Expression.Parameter(typeof(int), "value");
        var call = Expression.Call(thisParam, method, valueParam);
        var lambda = Expression.Lambda<Func<Foo, int, string>>(call, thisParam, valueParam);
        var func = lambda.Compile();
        var result = func((Foo)foo, 42);
        result.Dump();
    }
    Console.WriteLine("Create a DynamicMethod and compile it to a delegate that could be called on any instance.");
    {
        // Same thing as the previous expression sample. Foo need to be known at compile time and need
        // to be provided to the delegate.

        var type = foo.GetType();
        var method = type.GetMethod("Bar");

        var dynamicMethod = new DynamicMethod("Bar_", typeof(string), new [] { typeof(Foo), typeof(int) }, true);
        var il = dynamicMethod.GetILGenerator();
        il.DeclareLocal(typeof(string));
        il.Emit(OpCodes.Ldarg_0);
        il.Emit(OpCodes.Ldarg_1);
        il.Emit(OpCodes.Call, method);
        il.Emit(OpCodes.Ret);
        var func = (Func<Foo, int, string>)dynamicMethod.CreateDelegate(typeof(Func<Foo, int, string>));
        var result = func((Foo)foo, 42);
        result.Dump();
    }
    Console.WriteLine("Simulate closure without closures and in a lot more lines...");
    {
        var type = foo.GetType();
        var method = type.GetMethod("Bar");

        // The Foo class must be public for this to work, the "skipVisibility" argument of
        // DynamicMethod.CreateDelegate can't be emulated without breaking the .Net security model.

        var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(
            new AssemblyName("MyAssembly"), AssemblyBuilderAccess.Run);
        var module = assembly.DefineDynamicModule("MyModule");
        var tb = module.DefineType("MyType", TypeAttributes.Class | TypeAttributes.Public);

        var fooField = tb.DefineField("FooInstance", type, FieldAttributes.Public);
        var barMethod = tb.DefineMethod("Bar_", MethodAttributes.Public, typeof(string), new [] { typeof(int) });
        var il = barMethod.GetILGenerator();
        il.DeclareLocal(typeof(string));
        il.Emit(OpCodes.Ldarg_0); // this
        il.Emit(OpCodes.Ldfld, fooField);
        il.Emit(OpCodes.Ldarg_1); // arg
        il.Emit(OpCodes.Call, method);
        il.Emit(OpCodes.Ret);

        var closureType = tb.CreateType();

        var instance = closureType.GetConstructors().Single().Invoke(new object[0]);

        closureType.GetField(fooField.Name).SetValue(instance, foo);

        var methodOnClosureType = closureType.GetMethod("Bar_");

        var func = (Func<int, string>)Delegate.CreateDelegate(typeof(Func<int, string>), instance,
            closureType.GetMethod("Bar_"));
        var result = func(42);
        result.Dump();
    }
}






.net reflection open-source reflector