2008-10-05 23 views

Trả lời

4

Cách tốt nhất để đạt được điều này là bằng cách sử dụng đánh chặn, Có một vài cách để làm điều này, mặc dù tất cả chúng đều có xu hướng xâm lấn một phần. Người ta sẽ lấy tất cả các đối tượng của bạn từ ContextBoundObject. Here là một ví dụ về cách sử dụng cách tiếp cận này. Cách tiếp cận khác sẽ là sử dụng một trong các thư viện AOP hiện có để đạt được điều này. Một cái gì đó như DynamicProxy từ Castle Project là cốt lõi của nhiều trong số này. Dưới đây là một số liên kết: Spring.Net PostSharp Cecil

Có lẽ một số người khác, và tôi biết Castle Windsor, và Ninject cả cung cấp khả năng AOP trên đầu trang của các chức năng IoC.

Khi AOP được đặt đúng chỗ, bạn chỉ cần viết một lớp ngăn chặn ghi thông tin về phương thức gọi ra log4net.

Tôi thực sự sẽ không ngạc nhiên nếu một trong các khung công tác AOP sẽ cung cấp cho bạn loại chức năng đó ra khỏi hộp.

3

Bạn có thể sử dụng trình biên dịch sau như Postsharp. Các mẫu từ trang web nói về việc thiết lập một dấu vết để vào/thoát một phương pháp, mà là rất giống với những gì bạn muốn.

4

Tôi không chắc nhu cầu thực tế của bạn là gì, nhưng đây là tùy chọn cho thuê thấp. Đó là không chính xác "tự động", nhưng bạn có thể sử dụng StackTrace để bóc những thông tin bạn đang tìm kiếm trong một cách mà sẽ không đòi hỏi lập luận đi qua - tương tự như ckramer của đề nghị liên quan đến đánh chặn:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

using System.Diagnostics; 

namespace TracingSample 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      DoSomething(); 
     } 

     static void DoSomething() 
     { 
      LogEnter(); 

      Console.WriteLine("Executing DoSomething"); 

      LogExit(); 
     } 

     static void LogEnter() 
     { 
      StackTrace trace = new StackTrace(); 
      if (trace.FrameCount > 1) 
      { 
       string ns = trace.GetFrame(1).GetMethod().DeclaringType.Namespace; 
       string typeName = trace.GetFrame(1).GetMethod().DeclaringType.Name; 
       Console.WriteLine("Entering {0}.{1}.{2}", ns, typeName, trace.GetFrame(1).GetMethod().Name); 
      } 
     } 

     static void LogExit() 
     { 
      StackTrace trace = new StackTrace(); 
      if (trace.FrameCount > 1) 
      { 
       string ns = trace.GetFrame(1).GetMethod().DeclaringType.Namespace; 
       string typeName = trace.GetFrame(1).GetMethod().DeclaringType.Name; 
       Console.WriteLine("Exiting {0}.{1}.{2}", ns, typeName, trace.GetFrame(1).GetMethod().Name); 
      } 
     } 
    } 
} 

Bạn có thể kết hợp một cái gì đó giống như ví dụ ở trên với thừa kế, sử dụng một thành viên nào không ảo trong các loại hình cơ sở để biểu thị phương pháp hành động, sau đó gọi một thành viên ảo để thực sự làm việc:

public abstract class BaseType 
{ 
    public void SomeFunction() 
    { 

     LogEnter(); 
     DoSomeFunction(); 
     LogExit(); 
    } 

    public abstract void DoSomeFunction(); 
} 

public class SubType : BaseType 
{ 
    public override void DoSomeFunction() 
    { 
     // Implementation of SomeFunction logic here... 
    } 
} 

một lần nữa - không có nhiều "tự động "về điều này, nhưng nó sẽ hoạt động trên cơ sở hạn chế nếu bạn không yêu cầu thiết bị đo đạc trên mọi phương thức đơn lẻ ation.

Hy vọng điều này sẽ hữu ích.

+1

Mã này sẽ phù hợp với mã này để nắm bắt các giá trị tham số http://stackoverflow.com/a/6928253/1267778. Vì vậy, tôi có một cái gì đó như logService.LogEnter (arg1, arg2, arg3). Công cụ tuyệt vời – parliament

0

Bạn có thể sử dụng khung nguồn mở CInject trên CodePlex có LogInjector để đánh dấu mục nhập và thoát khỏi cuộc gọi phương thức.

Hoặc bạn có thể làm theo các bước được đề cập trong bài viết này trên Intercepting Method Calls using IL và tạo trình chặn của riêng bạn bằng cách sử dụng Reflection.Emit classes in C#.

0

Chức năng

Để mở rộng về câu trả lời của Jared, tránh mã lặp lại và bao gồm options for arguments:

private static void LogEnterExit(bool isEnter = true, params object[] args) 
{ 
    StackTrace trace = new StackTrace(true); // need `true` for getting file and line info 
    if (trace.FrameCount > 2) 
    { 
     string ns = trace.GetFrame(2).GetMethod().DeclaringType.Namespace; 
     string typeName = trace.GetFrame(2).GetMethod().DeclaringType.Name; 
     string args_string = args.Length == 0 ? "" : "\narguments: [" + args.Aggregate((current, next) => string.Format("{0},{1};", current, next))+"]"; 
     Console.WriteLine("{0} {1}.{2}.{3}{4}", isEnter ? "Entering" : "Exiting", ns, typeName, trace.GetFrame(2).GetMethod().Name, args_string); 
    } 
} 

static void LogEnter(params object[] args) 
{ 
    LogEnterExit(true, args); 
} 

static void LogExit(params object[] args) 
{ 
    LogEnterExit(false, args); 
} 

Cách sử dụng

static void DoSomething(string arg1) 
{ 
    LogEnter(arg1); 
    Console.WriteLine("Executing DoSomething"); 
    LogExit(); 
} 

Output

Trong giao diện điều khiển, đây sẽ là đầu ra nếu DoSomething được chạy với "blah" là arg1

Entering Program.DoSomething 
arguments: [blah] 
Executing DoSomething 
Exiting Program.DoSomething 
Các vấn đề liên quan