Intercept method calls
Asked Answered
I

6

6

Is there a way of intercepting some method calls without making any code changes around the method itself?

I don't need to inject any custom behaviour at runtime, only add custom performance logging to an existing project.

Introspect answered 18/8, 2014 at 14:54 Comment(3)
Have you tried Unity interception?Spanishamerican
Rosyln can- roslyn.codeplex.com/discussions/541688Contour
Aspect Oriented Programming might help youBrickwork
W
16

You want Aspect Oriented Programming.

There are 4 main flavours of AOP

  1. Runtime RealProxy based AOP
  2. Runtime subclass/virtual method AOP
  3. Post Compile IL weave AOP
  4. Precompile source code AOP

The above are ordered in order of speed of execution (slowest to fastest). Note the last two "should" be the same speed. However I expect the compiler to produce better IL than a Post Compile IL weave.

Runtime RealProxy AOP

The first camp usually includes IOC containers, since they lend themselves fairly well to this pattern, including and not limited to

  • Unity
  • Spring.NET
  • Castle.Windsor
  • Postsharp Express

Runtime subclass AOP

The second camp, is pretty rare, and the only project that I can think of off the top of my head is Entity Framework (which uses it for Lazy loading, however it isn't extensible, and cannot be customised).

Post Compile IL weave AOP

The third camp is pretty sparce also, since this technique is extremely complicated and difficult. This works by editing the dll assembly AFTER you have compiled, to add the extra code you want.

  • Postsharp Pro
  • Mono.Cecil
  • Fody (a mono.cecil wrapper)
  • Simple Injector

Source Generator

The final camp is relatively new. So new in fact, the only real entry is the experimental MS Roslyn. This is actually a C# compiler. So...yeah...its pretty magic.

The final camp is compile-time source generation. Today, that mostly means using Source Generators.

These allow you to generate source file that supplement your user generated source using partial classes. See https://github.com/amis92/csharp-source-generators for various examples.

Because the AOP is done before compilation, this kind of AOP has the best level of comparability and performance (more opportunities for optimization).

Summary

Now, if you are having real huge performance issues with performance critical code, I would suggest using Fody. What is awesome about this, is that it is free (unlike Postsharp Pro), it uses nuget and there is already a performance tool in Fody.MethodTimer.

Edit: Updated to reflect the new state of the art.

Weariful answered 18/8, 2014 at 15:15 Comment(3)
Postsharp also has an express edition which is free, depending on your usage this might be sufficient.Ario
Big thanks for the Fody reference, that's exactly all I was looking for, just some basic before/after method timers.Glasses
Fody MethodDecorator has a nasty bug in release build which is not yet fixed for 3 years ( github.com/Fody/MethodDecorator/issues/8 ). So we had to switch from Fody to RoslynValdavaldas
H
4

I have successfully used Castle DynamicProxy for that. It's more lightweight than a full fledged AOP framework, and can be used without an IoC container.

Haldan answered 18/8, 2014 at 15:9 Comment(0)
A
3

You could take a look at Aspect Oriented Programming, and see if it's a solution for your situation.

For instance: http://docs.castleproject.org/Default.aspx?Page=Introduction-to-AOP-With-Castle&NS=Windsor&AspxAutoDetectCookieSupport=1

http://fgheysels.blogspot.be/2006/11/aspect-oriented-programming-in-net.html

Anyway answered 18/8, 2014 at 14:55 Comment(0)
F
3

You can use any AOP Frameworks, like to Spring .NET or Unity, to intercept calls, before or after the method execute. Thus, you dont need to change your method code.

Foetation answered 18/8, 2014 at 14:57 Comment(0)
T
2

What you are looking for is Fody: https://github.com/fody

Its open source, stable and has lots of plugins for different AOP use cases. I am using it in a huge commercial application, and it is working very well. Installation and configuration is super easy and done within some minutes via nuget.

Some example plugins are:

  • PropertyChanged: (Injects INotifyPropertyChanged code into properties at compile time)
  • Anotar (Simplifies logging through a static class and some IL manipulation)
  • Method Timer (Injects some very basic method timing code)
  • ... and many more!

Requirements, examples and docs can be found on fodys github pages.

Turmeric answered 18/8, 2014 at 15:7 Comment(0)
K
2

Using PostSharp

[Serializable]
public class LogPerformance : OnMethodBoundaryAspect
{
    [NonSerialized]
    Stopwatch _stopWatch;

    public override void OnEntry(MethodExecutionArgs args)
    {
        _stopWatch = Stopwatch.StartNew();
        base.OnEntry(args);
    }

    public override void OnExit(PostSharp.Aspects.MethodExecutionArgs args)
    {
        Console.WriteLine(string.Format("[{0}] took {1} ms to execute",
          new StackTrace().GetFrame(1).GetMethod().Name,
            _StopWatch.ElapsedMilliseconds));
        base.OnExit(args);
    }
}

Use the aspect like so on a function:

[LogPerformance]
static void LongRunningCalc()
{
    //Your Code goes here
}

Simplified from : http://www.codeproject.com/Articles/337564/Aspect-Oriented-Programming-Using-Csharp-and-PostS

Kief answered 18/8, 2014 at 15:13 Comment(5)
Postsharp is not free :/Foetation
@Only a Curious Mind : I know that, but is that a reason to down vote a perfectly valid answer to the question asked?Brickwork
You are correct. Sorry. I can not remove the down vote now :(Foetation
Postsharp has an express edition which is free. In fact the sample posted here would work with the free edition. +1Ario
postsharp changed their pricing model whereby the free version is locked down to 10 classes per project.Anechoic

© 2022 - 2024 — McMap. All rights reserved.