Как я могу отследить вызов метода после заказа?
Я хотел бы отслеживать вызовы методов, следующие за порядком. Поскольку ведение журнала будет применяться на производстве, поэтому я не хочу так сильно изменять свой код.
До сих пор я хотел бы применить перехватчик в Unity для отслеживания вызова метода, я почти закончил. Тем не менее, распечатка журнала не то, что я ожидаю. Все что мне нужно это:
Из кода peusedo, как показано ниже:
void method1()
{
call method2();
}
Журнал трассировки должен иметь следующий формат:
Ввод вызова метода 1/ Ввод вызова метода 2
Вызов метода вызова 2 / Вызов метода вызова 1
Кстати, мое приложение работает на.Net Framework версии 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; }
}
Извините за мой код. Это довольно долго.
1 ответ
Вот класс, обеспечивающий эту функциональность:
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
}
}
Примечание: если вы используете предыдущие версии C#, которые не поддерживают [CallerMemberName]
атрибут, вы должны предоставить memberName
в явном виде.
Также вы можете использовать этот вспомогательный класс, который я использую в версии до.NET 4.5:
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
}