Как отслеживать каждый метод, называемый
У меня есть существующий проект, в котором я хотел бы узнать все сделанные вызовы и, возможно, записать в файл журнала.
Я смотрел в этой теме, но не очень помог.
Я попробовал PostSharp, и пример показывает, как его достичь. Но мне нужно добавить атрибут для каждого метода darn. Быть существующим проектом, используя множество методов, которые не являются допустимым вариантом.
Есть ли другие способы, с помощью которых я могу быстро отслеживать все сделанные звонки?
Ответы
Ответ 1
Вы можете сделать это с помощью Unity Interception
См. статью для примера. В статье используются атрибуты, но в моем примере кода ниже используется система впрыска зависимостей (кодирование с интерфейсом) для настройки перехвата.
Если вы хотите войти в журнал MyClass
, это будет выглядеть примерно так:
- Создайте интерфейс, содержащий все методы в
MyClass
= > IMyClass
- Вы настраиваете InterfaceInterception (например, я сделал это ниже) ИЛИ есть несколько других способов его настройки. См. здесь для всех параметров.
- Вы настроите политику для перехвата всех методов, которые соответствуют
IMatchingRule
.
- Теперь все вызовы будут перехвачены с помощью ICallHandler.
код:
//You will use the code like this:
MyContainer container = new MyContainer();
//setup interception for this type..
container.SetupForInteception(typeof(IMyClass));
//what happens here is you get a proxy class
//that intercepts every method call.
IMyClass cls = container.Resolve<IMyClass>();
//You need the following for it to work:
public class MyContainer: UnityContainer
{
public MyContainer()
{
this.AddNewExtension<Interception>();
this.RegisterType(typeof(ICallHandler),
typeof(LogCallHandler), "MyCallHandler");
this.RegisterType(typeof(IMatchingRule),
typeof(AnyMatchingRule), "AnyMatchingRule");
this.RegisterType<IMyClass, MyClass>();
}
//apparently there is a new way to do this part
// http://msdn.microsoft.com/en-us/library/ff660911%28PandP.20%29.aspx
public void SetupForInteception(Type t)
{
this.Configure<Interception>()
.SetInterceptorFor(t, new InterfaceInterceptor())
.AddPolicy("LoggingPolicy")
.AddMatchingRule("AnyMatchingRule")
.AddCallHandler("MyCallHandler");
}
}
//THIS will match which methods to log.
public class AnyMatchingRule : IMatchingRule
{
public bool Matches(MethodBase member)
{
return true;//this ends up loggin ALL methods.
}
}
public class LogCallHandler : ICallHandler
{
public IMethodReturn
Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
//All method calls will result in a call here FIRST.
//IMethodInvocation has an exception property which will let you know
//if an exception occurred during the method call.
}
}
Ответ 2
PostSharp, безусловно, предлагает способ применения аспект к нескольким целям без четкого описания атрибутов. См. Атрибуты многоадресной передачи.
При разработке (многоадресной) аспект вы должны указать его использование:
[MulticastAttributeUsage(MulticastTargets.Method, TargetMemberAttributes = MulticastAttributes.Instance)]
[AttributeUsage(AttributeTargets.Assembly|AttributeTargets.Class|AttributeTargets.Method, AllowMultiple = true)]
[Serializable]
public class TraceAttribute : MethodInterceptionAspect
{
// Details skipped.
}
И затем примените аспект таким образом, который охватывает ваш прецедент (например, все публичные члены в пространстве имен AdventureWorks.BusinessLayer):
[assembly: Trace( AttributeTargetTypes="AdventureWorks.BusinessLayer.*", AttributeTargetMemberAttributes = MulticastAttributes.Public )]
Ответ 3
Используйте Profiler в режиме трассировки. Затем вы увидите, как все называет друг друга и где тратится время. Помимо коммерческих профайлеров есть и бесплатные.
Для управляемого кода есть NP Profiler, что неплохо.
Если вы хотите углубиться, вы можете использовать Performance Performance Toolkit, который дает вам полную информацию по всем темам и как взаимодействовать друг с другом Если вы хотите знать. Единственное различие заключается в том, что вы получаете стеки от ядра до управляемых фреймов.
Если этого недостаточно, вы можете запрограммировать свой код с помощью библиотеки трассировки (автоматически с помощью PostSharp,....) или вручную или с помощью макроса для каждого исходного файла.
Я создал небольшую библиотеку трассировки, которая довольно быстрая и настраиваемая. См. здесь. В качестве уникальной функции он может автоматически отслеживать любое исключенное исключение.
private void SomeOtherMethod()
{
using (Tracer t = new Tracer(myType, "SomeOtherMethod"))
{
FaultyMethod();
}
}
private void FaultyMethod()
{
throw new NotImplementedException("Hi this a fault");
}
Здесь идет вывод:
18:57:46.665 03064/05180 <{{ > ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeMethod
18:57:46.668 03064/05180 <{{ > ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeOtherMethod
18:57:46.670 03064/05180 < }}< ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeOtherMethod Exception thrown: System.NotImplementedException: Hi this a fault
at ApiChange.IntegrationTests.Diagnostics.TracingTests.FaultyMethod()
at ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeOtherMethod()
at ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeMethod()
at ApiChange.IntegrationTests.Diagnostics.TracingTests.Demo_Show_Leaving_Trace_With_Exception()
18:57:46.670 03064/05180 < }}< ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeOtherMethod Duration 2ms 18:57:46.689 03064/05180 < }}< ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeMethod Duration 24ms