J'ai un projet existant où je voudrais découvrir tous les appels en cours et peut-être les vider dans un fichier journal.
J'ai jeté un coup d'œil à ce fil , mais n'a pas beaucoup aidé. J'ai essayé PostSharp, et l'exemple montre comment y parvenir. Mais je dois ajouter un attribut à chaque méthode sacrément. Être un projet existant, avec de nombreuses méthodes qui n'est pas une option réalisable.
Existe-t-il un autre moyen par lequel je peux retracer rapidement tous les appels effectués?
Vous pouvez le faire avec nity Interception
Voir ceci article pour un exemple . L'article utilise des attributs, mais mon exemple de code ci-dessous utilise le système d'injection de dépendance (codage vers une interface) pour configurer l'interception.
Si vous voulez vous connecter MyClass
, cela ressemble à ceci:
MyClass
=> IMyClass
IMatchingRule
.Code:
//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.
}
}
Utilisez un profileur en mode de traçage. Ensuite, vous verrez comment tout s'appelle et où le temps est passé. Outre les profileurs commerciaux, il existe également des profils gratuits. Pour le code managé, il y a NP Profiler qui est assez bon.
Si vous voulez aller plus loin, vous pouvez utiliser Windows Performance Toolkit qui vous donne des informations complètes sur tous les threads et comment interagir les uns avec les autres si vous voulez le savoir. La seule différence est que vous obtenez des piles allant du noyau jusqu'à vos trames gérées.
Si cela ne suffit pas, vous pouvez instrumenter votre code avec une bibliothèque de suivi (soit automatiquement avec PostSharp, ....) soit manuellement ou avec une macro pour chaque fichier source. J'ai créé une petite bibliothèque de traçage qui est assez rapide et hautement configurable. Voir ici . En tant que fonctionnalité unique, il peut suivre automatiquement toute exception levée.
private void SomeOtherMethod()
{
using (Tracer t = new Tracer(myType, "SomeOtherMethod"))
{
FaultyMethod();
}
}
private void FaultyMethod()
{
throw new NotImplementedException("Hi this a fault");
}
Voici la sortie:
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
PostSharp offre certainement un moyen d'appliquer un aspect à plusieurs cibles sans les décorer explicitement d'attributs. Voir Attributs de multidiffusion .
Lors du développement d'un aspect (multicast), vous devez spécifier son utilisation:
[MulticastAttributeUsage(MulticastTargets.Method, TargetMemberAttributes = MulticastAttributes.Instance)]
[AttributeUsage(AttributeTargets.Assembly|AttributeTargets.Class|AttributeTargets.Method, AllowMultiple = true)]
[Serializable]
public class TraceAttribute : MethodInterceptionAspect
{
// Details skipped.
}
Et appliquez ensuite l'aspect d'une manière qui couvre votre cas d'utilisation (par exemple, tous les membres publics dans l'espace de noms AdventureWorks.BusinessLayer):
[Assembly: Trace( AttributeTargetTypes="AdventureWorks.BusinessLayer.*", AttributeTargetMemberAttributes = MulticastAttributes.Public )]