Вопрос

Рассмотрим следующий тривиальный код:

using System;   
class Test
{
    delegate int FooDelegate(int i);
    FooDelegate Foo = FooImplementation;
    static int FooImplementation(int i)
    {
        return i + 1;
    }

    public static void Main()
    {
         Foo(1);
    }
}

То, что я хотел бы сделать, это ввести какой-то код отладки в делегат Foo, который будет эквивалентен:

FooDelegate Foo = delegate(int i)
{
    try
    {
        DebugPrologue();
        return FooImplementation(i);
    }
    finally
    {
        DebugEpilogue();
    }
};

Твист в том, что я должен быть в состоянии сделать это в время выполнения, поэтому методы комбинированного времени и последующие методы находятся в рецензии.

Мой первоначальный подход использовал Delage.comBine () для добавления методов пролога и эпилюга в делегат FOO. Увы, это не будет работать так, как он помогает возвращать значения.

Моя текущая идея состоит в том, чтобы использовать System.reflection.emit и DynamicMethod в качестве потенциального решения. Насколько я могу сказать, мне нужно получить методинфо для FOOOIMPLEMENTATION, получите свой метод, преобразуйте это на динамику и введите мою попытку, наконец-то блок в это.

К сожалению, я не имею абсолютно не знаю, как это сделать. Кто-нибудь готов давать руку? Или у вас есть еще одна (предпочтительно простая) идея?

Редактировать: использование-корпус здесь отладки привязки OpenGL (http://www.opentk.com). Мы должны вводить 2226 методов с дико разными параметрами, поэтому необходим общий подход.

Это было полезно?

Решение 6

То, что я, наконец, оказался, это реализовать свое собственное переписанное решение с использованием Mono.cecil. Просто, быстро и работает нормально. К сожалению, это должно быть сделано как событие после сборки, поэтому это на самом деле не впрыска кода выполнения.

Другие советы

Вы можете использовать выражения.

var param = Expression.Parameter(typeof(int), "i");

Foo = Expression.Lambda(
         Expression.TryFinally(
            Expression.Block(
               <expression for DebugPrologue>,
               Expression.Invoke(<expression for FooImplementation>, param)),
            <expression for DebugEpilogue>),
         param)
      .Compile();

Таким образом, вы можете построить выражения для пролога и эпилога во время выполнения.

Обратите внимание, что вы пытаетесь сделать, но если это просто перенаправляет FooImplementation это указано на Foo Поле тогда вы можете просто сделать:

class Test
{
    delegate int FooDelegate(int i);
    static FooDelegate Foo = FooImplementation;

    static int FooImplementation(int i)
    {
        return i + 1;
    }

    public static void Main()
    {
        Inject();
        Foo(1);
    }


    public static void Inject()
    {
        var oldImpl = Foo;

        Foo = i =>
            {
                try
                {
                    BeginDebug();
                    return oldImpl(i);
                }
                finally
                {
                    EndDebug();
                }
            };
    }

    public static void BeginDebug()
    {
        Console.WriteLine("Begin Foo");
    }

    public static void EndDebug()
    {
        Console.WriteLine("End Foo");
    }
}

Конечно, ввод не должен быть в том же классе, однако, если поле / имущество не публично доступно, вам придется использовать отражение, чтобы сделать это, все еще не так сложно.

Вы считаете, что используете что-то вроде: postsharp?http://www.sharpcrafters.com/postsharp.

или предпринимательская политика библиотеки впрыскивается?http://msdn.microsoft.com/en-us/library/ff650672.aspx.

Или даже mono.cecil?http://www.mono-project.com/Cecil.

Typemock также может быть жизнеспособным решением вашей проблемы:http://www.typemock.com/

Вы также можете использовать RealProxy Class (http://msdn.microsoft.com/en-us/library/system.runtime.remoting.proxies.realProxy.aspx) для создания собственного прокси во время выполнения, которые сначала позвоните в дополнительный код а затем вызвать фактический метод.

Вы также можете попробовать Цилиндр На CodeePlex для ввода кода в управляемый код (C # или VB.NET) с большой легкостью.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top