如何跟踪顺序之后的方法调用

本文关键字:之后 方法 调用 顺序 何跟踪 跟踪 | 更新日期: 2023-09-27 18:16:03

我想按照顺序跟踪方法调用。因为日志记录将应用于生产,所以我不想修改我的代码这么多。

到目前为止,我想在Unity上应用一个拦截器来跟踪方法调用,我几乎完成了。然而,打印出来的日志并不是我所期望的。我只需要:

From peusedo code如下:

  void method1()
  {
     call method2();
  }

跟踪日志的格式应该如下:

进入方法调用1/进入方法调用2

离开方法呼叫2/离开方法呼叫1

顺便说一句,我的应用程序运行在。net框架版本4上。

程序如下:

    static void Main(string[] args)
    {
        var container = new UnityContainer();
        container.RegisterType<IInterface1, Implementation1>();
        container.RegisterType<IInterface2, Implementation2>();
        container.RegisterInstance(typeof (IUnityContainer), container);
        container.AddNewExtension<Interception>();
        container.Configure<Interception>()
        .SetInterceptorFor<IInterface1>(new InterfaceInterceptor());
        container.Configure<Interception>()
        .SetInterceptorFor<IInterface2>(new InterfaceInterceptor());
        var service = container.Resolve<IInterface1>();
        var results = service.GetListCustomerIdByName("abc");
        Console.ReadLine();
     }
public interface IInterface1
    {
        [Trace]
        IEnumerable<Guid> GetListCustomerIdByName(string name);
    }
    public class Implementation1 : IInterface1
    {
        private readonly IInterface2 _impl;
        public Implementation1(IUnityContainer container)
        {
            _impl = container.Resolve<IInterface2>();
        }
        public IEnumerable<Guid> GetListCustomerIdByName(string name)
        {
            return _impl.GetListCustomerIdByName(name);
        }
    }
public interface IInterface2
{
    [Trace]
    IEnumerable<Guid> GetListCustomerIdByName(string name);
}
public class Implementation2 : IInterface2
{
    public IEnumerable<Guid> GetListCustomerIdByName(string name)
    {
        yield return Guid.NewGuid();
    }
}

public class TraceAttribute : HandlerAttribute
    {
        public override ICallHandler CreateHandler(IUnityContainer container)
        {
            return new TraceCallHandler();
        }
    }
public class TraceCallHandler : ICallHandler
{
    public IMethodReturn Invoke(IMethodInvocation input, 
   GetNextHandlerDelegate getNext)
    {
        Console.WriteLine("Entering " + input.MethodBase.Name +"()");
        InvokeHandlerDelegate next = getNext();
        IMethodReturn result = next(input, getNext);
        string returnValueStr = 
        result.ReturnValue == null ? "(void)" : result.ReturnValue.ToString();
        if (result.Exception != null)
        {
            Console.WriteLine("Exception: {0}", result.Exception);
        }
        Console.WriteLine("Leaving 
        " +input.MethodBase.Name + "() Return Value: [" + returnValueStr + "]");
        return result;
    }
    public int Order { get; set; }
}

抱歉我的代码。它很长。

如何跟踪顺序之后的方法调用

下面是一个提供该功能的类:

class Scope : IDisposable
{
    Action<string> _logger;
    string _memberName;
    public Scope(Action<string> logger, [CallerMemberName] string memberName = "N/A")
    {
        if (logger == null) throw new ArgumentNullException();
        _logger = logger;
        _memberName = memberName;
        _logger(string.Format("Entered {0}", _memberName));
    }
    public void Dispose()
    {
        _logger(string.Format("Exited {0}", _memberName));
    }
}

使用它:

static void MyMethod()
{
    using (new Scope(s => Console.WriteLine(s)))
    {
        // boddy
    }
}

注意:如果你使用不支持[CallerMemberName]属性的旧版本c#,你必须显式地提供memberName

你也可以使用这个我自己在。net 4.5之前版本中使用的helper类:

public static class Here
{
    public static string Spot(HereOptions options)
    {
        return MakeMessageInternals(options, 3);
    }
    public static string Type
    {
        get
        {
            return MakeMessageInternals(HereOptions.Type, 3);
        }
    }
    public static string Member
    {
        get
        {
            return MakeMessageInternals(HereOptions.Member, 3);
        }
    }
    public static string FileLine
    {
        get
        {
            return MakeMessageInternals(HereOptions.FileLine, 3);
        }
    }
    public static string FileName
    {
        get
        {
            return MakeMessageInternals(HereOptions.FileName, 3);
        }
    }
    static StackFrame GetCaller(int index) { return new StackTrace(true).GetFrame(index); }
    static string MakeMessageInternals(HereOptions options, int index)
    {
        StackFrame first = null;
        var _FileName = new StringBuilder();
        var _FileLine = new StringBuilder();
        var _Member = new StringBuilder();
        var _Type = new StringBuilder();
        if ((options & HereOptions.FileName) == HereOptions.FileName)
        {
            first = GetCaller(index);
            if (first != null)
            {
                var fn = first.GetFileName();
                if (!string.IsNullOrEmpty(fn))
                    _FileName.Append(" " + Path.GetFileName(fn));
            }
        }
        if ((options & HereOptions.FileLine) == HereOptions.FileLine)
        {
            if (first == null)
                first = GetCaller(index);
            if (first != null)
            {
                var ln = first.GetFileLineNumber();
                _FileLine.Append(" #" + ln);
            }
        }
        if ((options & HereOptions.Member) == HereOptions.Member)
        {
            if (first == null)
                first = GetCaller(index);
            if (first != null)
            {
                var mn = first.GetMethod().Name;
                _Member.Append(" " + mn);
            }
        }
        if ((options & HereOptions.Type) == HereOptions.Type)
        {
            if (first == null)
                first = GetCaller(index);
            if (first != null)
            {
                var dt = first.GetMethod().DeclaringType;
                _Type.Append(string.Format(" ({0})", dt));
            }
        }
        var messageInternal = string.Format("{0}{1}{2}{3}",
            _FileName,
            _FileLine,
            _Member,
            _Type).Trim();
        return messageInternal;
    }
}
[Flags]
public enum HereOptions : byte
{
    None = 0,
    FileName = 1,
    FileLine = 2,
    Member = 4,
    Type = 8,
    All = 15
}