3

I would like to use interception to add logging in my application without having to fill my code with lines like: "Logger.Log(Something);"

I am aware this is considered a "Cross-cutting concern" which means it can be well handled using Aspect Oriented Programming. I considered the following two options which do not work well for me. 1- Postsharp : Can't be used on community edition 2- Unity Framework : Provides Interface interception, Virtual Methods and inheritance of MarshalByRef . None of these options will work because I can not write a new interface for every class in my project. I can not make all the methods virtual and I can not break the inheritance structure and limit inheritance to MarshalByRef

I might be thinking about the problem the wrong way. Thanks in advance for helping .

mymo
  • 239
  • 2
  • 11
  • PostSharp can be used with VS Community Edition if that is what you mean. Please provide details on why you cannot use PostSharp. – Daniel Balas Mar 15 '15 at 14:34
  • Why do you need to fill your code with "Logger.Log"? – Saravanan Mar 15 '15 at 15:08
  • @DanielBalas Last time I chatted with postsharp support I was told the postsharp professional version does not work with express/community. If Postsharp professional logging module can be used with VS community this will be good enough for me. – mymo Mar 15 '15 at 15:29
  • @Saravanan Do you know a better way to log the steps or errors that occur during the application execution? Thanks for your response – mymo Mar 15 '15 at 15:33
  • 1
    If it is about errors/exceptions, let it bubble up to the application start and log there. If you need to add information that is available only at specific layer, just add that information to the exception's "Data" property and format while writing. Use logging at only one place. – Saravanan Mar 15 '15 at 15:57
  • 1
    @MoatazElGamal Well, Express cannot be supported because of Microsoft licensing policy. Community is fully supported since November 2014 I think. – Daniel Balas Mar 16 '15 at 12:57
  • @mymo, have you looked as Castle Project's DynamicProxy? – Kirill Shlenskiy Nov 24 '16 at 02:02

2 Answers2

2

Take a look at the Real Proxy class. You can use it to implement the decorator pattern fairly easily:

public class LoggingDecorator<T> : RealProxy
{
    private readonly T _decorated;

    public LoggingDecorator(T decorated)
        : base(typeof(T))
    {
        _decorated = decorated;
    }

    public override IMessage Invoke(IMessage msg)
    {
         // Add logging action here

         var methodCall = msg as IMethodCallMessage;
         var methodInfo = methodCall.MethodBase as MethodInfo;

         // Invoke actual method
         var result = methodInfo.Invoke(_decorated, methodCall.InArgs);

         return new ReturnMessage(result, null, 0, methodCall.LogicalCallContext, methodCall);
    }
}

If you're using IoC you should be able to register components with the decorator.

RagtimeWilly
  • 5,265
  • 3
  • 25
  • 41
  • 2
    Performance cost of invoking a method using Reflection can be quite high (especially in case of logging). I would suggest using Reflection.Emit/Linq Expressions and a caching mechanism if performance is an issue. – Daniel Balas Mar 15 '15 at 14:39
1

Try NConcern

It is a simple AOP framework (on which I actively work) allowing you to apply cross cutting concern at runtime without changing you build system, inheritance forcing and factory/proxy pattern. It can handle non virtual methods because it use code injection.

Logging aspect

//define aspect to describe how handle logging
public class Logging : Aspect
{
    //describe how to log
    override protected IEnumerable<Advice<T>> Advise(MethodInfo method)
    {
        //after method call, log method name.
        yield return Advice<T>.Basic.After(() => Logger.Log(method.Name));
    }
}

Sample class

public sealed class SampleClass
{
    public void SampleMethod()
    {
    }
}

Here how to use

var logging = new Logging();

//inject logging aspect to SampleClass
logging.Manage<SampleClass>();

//now when SampleMethod is called, it is logged.

There is only minimal performance cost (original call + your delegate).

Tony THONG
  • 772
  • 5
  • 11