Логирование при входе и при выходе из метода
От: higohertz  
Дата: 26.07.12 03:37
Оценка:
Добрый день!

Осваиваю С# и вот появилась такая задачка.
Необходимо вывести строчку при входе в метод и при выходе из него.
При этом как можно меньше перегружать тело метода ненужными инструкциями.
В С++ проблем не было (привел пример).

Единственное, что пришло в голову:
void Func()
{
  try
  {
     Console.WriteLine("Enter");
     .... (какой-то код с Exceptions - ами и return - ами)
  }
  finally
  {
     Console.WriteLine("Leave")
  }
}


На С++ делалось проще. А в С# фиг знает когда деструктор вызовется:
class Logger()
{
  Logger() {cout << "Enter"}
  ~Logger() {cout << "Leave"}
}

void Func()
{
   Logger log;
   .... (какой-то код с Exceptions - ами и return - ами)
}
Re: Логирование при входе и при выходе из метода
От: -VaS- Россия vaskir.blogspot.com
Дата: 26.07.12 04:45
Оценка:
PostSharp.
Dynamic proxy (например, castle).
Interceptor в DI контейнерах.
Ну а если совсем красиво — Nemerle.
Re: Логирование при входе и при выходе из метода
От: stomsky Россия  
Дата: 26.07.12 04:53
Оценка:
Здравствуйте, higohertz, Вы писали:

H>На С++ делалось проще. А в С# фиг знает когда деструктор вызовется:


Гм... оригинальный способ... Спасибо за идею!
Аналог на C# (конечно всякие PostSharp и прочие примочки — более профессионально смотрятся, зато ниже просто вариант "перевода" с C++ на C#):

public class Logger : IDisposable
{
  public Logger()
  {
    Console.WriteLine("Начало выполнения...");
  }
  public void Dispose()
  {
    Console.WriteLine("Окончание выполнения...");
  }
}
void Func()
{
  using (Logger log = new Logger())
  {
    Console.WriteLine("Всякие полезные действия...");
  }
}
Красота — наивысшая степень целесообразности. (c) И. Ефремов
Re: Логирование при входе и при выходе из метода
От: GGoga  
Дата: 26.07.12 06:59
Оценка:
Здравствуйте, higohertz, Вы писали:

H>Осваиваю С# и вот появилась такая задачка.

H>Необходимо вывести строчку при входе в метод и при выходе из него.
H>При этом как можно меньше перегружать тело метода ненужными инструкциями.
H>В С++ проблем не было (привел пример).

H>Единственное, что пришло в голову:

H>
H>void Func()
H>{
H>  try
H>  {
H>     Console.WriteLine("Enter");
H>     .... (какой-то код с Exceptions - ами и return - ами)
H>  }
H>  finally
H>  {
H>     Console.WriteLine("Leave")
H>  }
H>}
H>


Можно так:
public static void DoAction(Action action)
{
  try
  {
     Console.WriteLine("Enter");
     action();
  }
  finally
  {
     Console.WriteLine("Leave")
  }
}

// ...

{
   DoAction(Func);
}


Естественно, это самый примитивный способ. Обычно метод DoAction тюнится всякими Stopwatch-ами и подробным логом.
Re[2]: Логирование при входе и при выходе из метода
От: stomsky Россия  
Дата: 26.07.12 07:52
Оценка: 6 (1)
S>Здравствуйте, higohertz, Вы писали:

А еще потрясающий, по-моему, по оригинальности способ мне предложил здесь
Автор: Sinclair
Дата: 29.02.12
Sinclar (пользуясь случаем, снимаю шляпу еще раз ).
Правда этот вариант ИМХО чуть сложнее, чем предыдущий, но зато тоже красивый!

Схематически можно реализовать примерно так:
// собственно код "библиотеки трассировки":
public delegate void EasyMethodHandler();
public static class Tracer
{
  public static void Trace(EasyMethodHandler h)
  {
    Console.WriteLine("Enter");
    try
    {
      h();
    }
    finally
    {
      Console.WriteLine("Leave");
    }
  }
}

// класс, вызовы методов которого будем трассировать
public class ClassForeTest
{
  public void EasyDoSomething()
  {
    Console.WriteLine("Вызван метод EasyDoSomething");
  }
  public void StrParamDoSomething(string str)
  {
    Console.WriteLine(string.Format("Вызван метод StrParamDoSomething о строковым параметром '{0}'", str));
  }
}

// а вот дальше мы собственно пользуемся трассировкой:

...
ClassForeTest obj = new ClassForeTest();
string s = "***any string***";

// можно трассировать вызов каждого метода так:
Tracer.Trace(() => obj.EasyDoSomething());
Tracer.Trace(() => obj.StrParamDoSomething(s));

// или так (то же самое, что две предыдущие строки, только более многословно):
Tracer.Trace(delegate { obj.EasyDoSomething(); });
Tracer.Trace(delegate { obj.StrParamDoSomething(s); });

// а можно трассировать вызов последовательности нескольких методов вот так:
Tracer.Trace(deleagte
{
  obj.EasyDoSomething();
  obj.StrParamDoSomething(s);
});
...
Красота — наивысшая степень целесообразности. (c) И. Ефремов
Re[3]: Логирование при входе и при выходе из метода
От: hardcase Пират http://nemerle.org
Дата: 26.07.12 08:39
Оценка: +1
Здравствуйте, stomsky, Вы писали:

S>>Здравствуйте, higohertz, Вы писали:


S>А еще потрясающий, по-моему, по оригинальности способ мне предложил здесь
Автор: Sinclair
Дата: 29.02.12


Способ хорош только если всем наплевать оверхеды использования памяти и косвености вызовов. Каждый Trace может вылиться в изготовление двух объектов: делегата и замыкания для него.
http://nemerle.org/Banners/?t=Developer!&g=dark /* иЗвиНите зА неРовнЫй поЧерК */
Re[4]: Логирование при входе и при выходе из метода
От: stomsky Россия  
Дата: 26.07.12 09:55
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Способ хорош только если всем наплевать оверхеды использования памяти и косвености вызовов. Каждый Trace может вылиться в изготовление двух объектов: делегата и замыкания для него.

Ну минусы есть, конечно! Но ведь как красиво!
К тому же применение какого-нибудь PostSharp-а разве будет экономичнее? (я не знаю, я спрашиваю )
Ну а на крайний случай сойдет и первый метод, полученный тупым переводом из C++'ого кода топикстартера (который с реализацией интерфейса IDisposable)
Тут уж, как и всегда при проектировании, надо искать компромисс между красотой и эффективностью.
А хочется И того, И другого — выше уже предлагали Немерле... Тока его же отдельно учить надо, да и не мэйнстрим это пока...
Красота — наивысшая степень целесообразности. (c) И. Ефремов
Re[5]: Логирование при входе и при выходе из метода
От: hardcase Пират http://nemerle.org
Дата: 26.07.12 10:17
Оценка:
Здравствуйте, stomsky, Вы писали:

S>Здравствуйте, hardcase, Вы писали:


H>>Способ хорош только если всем наплевать оверхеды использования памяти и косвености вызовов. Каждый Trace может вылиться в изготовление двух объектов: делегата и замыкания для него.

S>Ну минусы есть, конечно! Но ведь как красиво!

С точки зрения C# наверно это красиво. Для меня красиво как-то так:
trace
{
  x.Foo();
  y.Bar(z);
}


S>К тому же применение какого-нибудь PostSharp-а разве будет экономичнее? (я не знаю, я спрашиваю )


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


В C# я использовал бы вариант на тему using:
using(new Trace("..."))
{
  x.Foo();
  y.Bar(z);
}
http://nemerle.org/Banners/?t=Developer!&g=dark /* иЗвиНите зА неРовнЫй поЧерК */
Re[6]: Логирование при входе и при выходе из метода
От: hardcase Пират http://nemerle.org
Дата: 26.07.12 10:18
Оценка:
Здравствуйте, hardcase, Вы писали:

H>В C# я использовал бы вариант на тему using:

H>
H>using(new Trace("..."))
H>{
H>  x.Foo();
H>  y.Bar(z);
H>}
H>


В этом случае допустимо Trace сделать структурой.
http://nemerle.org/Banners/?t=Developer!&g=dark /* иЗвиНите зА неРовнЫй поЧерК */
Re: Логирование при входе и при выходе из метода
От: Sinclair Россия http://corp.ingrammicro.com/Solutions/Cloud.aspx
Дата: 26.07.12 10:21
Оценка:
Здравствуйте, higohertz, Вы писали:
H>В С++ проблем не было (привел пример).
Ну, если вас устроит решение, максимально близкое к C++, то надо делать вот так:

public class Logger: IDisposable
{
  Logger() { Console.WriteLine("Enter"); }
  void Dispose() {Console.WriteLine("Leave");}
}

void Func()
{
   using(new Logger())
   {
   .... //(какой-то код с Exceptions - ами и return - ами)
   }
}
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
http://rsdn.org/File/5743/rsdnaddict.GIF
Re[2]: Логирование при входе и при выходе из метода
От: hardcase Пират http://nemerle.org
Дата: 26.07.12 10:25
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, higohertz, Вы писали:

H>>В С++ проблем не было (привел пример).
S>Ну, если вас устроит решение, максимально близкое к C++, то надо делать вот так:

Только конечно
public struct Logger: IDisposable
{
  Logger() { Console.WriteLine("Enter"); }
  void Dispose() {Console.WriteLine("Leave");}
}


Зачем нам лишние объекты?
http://nemerle.org/Banners/?t=Developer!&g=dark /* иЗвиНите зА неРовнЫй поЧерК */
Re[6]: Логирование при входе и при выходе из метода
От: stomsky Россия  
Дата: 26.07.12 10:41
Оценка:
Здравствуйте, hardcase, Вы писали:
H>С точки зрения C# наверно это красиво. Для меня красиво как-то так:
H>
H>trace
H>{
H>  x.Foo();
H>  y.Bar(z);
H>}
H>

Хм, мне Ваш вариант тоже более красивым кажется, но я подозреваю, что это уже упоминавшийся выше Немерл, а "trace" в данном примере — это макрос?
А изначально вопрос именно о C# ставился...

H>В C# я использовал бы вариант на тему using:

H>
H>using(new Trace("..."))
H>{
H>  x.Foo();
H>  y.Bar(z);
H>}
H>

А у этого способа есть другой недостаток: можно "забыть" обернуть создание структуры (согласен, что в данном случае у структуры будут преимущества перед классом) в using. Хотя с точки зрения производительности преимущество.
Ищите компромисс...
Красота — наивысшая степень целесообразности. (c) И. Ефремов
Re[7]: Логирование при входе и при выходе из метода
От: hardcase Пират http://nemerle.org
Дата: 26.07.12 10:56
Оценка:
Здравствуйте, stomsky, Вы писали:

S>Хм, мне Ваш вариант тоже более красивым кажется, но я подозреваю, что это уже упоминавшийся выше Немерл, а "trace" в данном примере — это макрос?

S>А изначально вопрос именно о C# ставился...

Да, это макрос. Кажется, в стандартной поставке даже что-то подобное было.

S>А у этого способа есть другой недостаток: можно "забыть" обернуть создание структуры (согласен, что в данном случае у структуры будут преимущества перед классом) в using. Хотя с точки зрения производительности преимущество.


Забыть на самом деле сложно, если знать способ использования логгера. Кроме того в вижаке есть возможность прогнать анализ кода — он выявит места, где программист забыл сказать Dispose.
http://nemerle.org/Banners/?t=Developer!&g=dark /* иЗвиНите зА неРовнЫй поЧерК */
Re[3]: Логирование при входе и при выходе из метода
От: stomsky Россия  
Дата: 26.07.12 10:58
Оценка: 6 (1)
Здравствуйте, hardcase, Вы писали:

H>Только конечно

H>
H>public struct Logger: IDisposable
H>{
H>  Logger() { Console.WriteLine("Enter"); }
H>  void Dispose() {Console.WriteLine("Leave");}
H>}
H>


Ну тогда уж давайте будем совсем корректными, ибо: "Struct cannot contain a parameterless constructor", — и сделам так:
public struct Logger: IDisposable
{
  public static Logger BeginLogging()
  {
    Console.WriteLine("Enter");
    return new Logger();
  }
  public void Dispose()
  {
    Console.WriteLine("Leave");
  }
}


и вызов соотвественно:

using (Logger.BeginLogging())
{
  Console.WriteLine("Do anything");
}
Красота — наивысшая степень целесообразности. (c) И. Ефремов
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.