Search code examples
c#.net-coreaop

AOP in Dotnet core : Dynamic Proxy with Real Proxy in Dotnet core


I am migrating my application from .Net Framework 4.5.1 to Dot Net Core. I was using RealProxy Class for logging user information and parameters on BeforeExecute and AfterExecute ( like this link)

Now it seems there is no such a thing in Dot core.Plus I don't want to use third parties.I found this link that is using Actionfilter but it won't do the job.

my question is How can I implement Dynamic Proxy in Dot net Core? Is there any alternate for RealProxy Class?


Solution

  • As I already answered in RealProxy in dotnet core?, RealProxy doesn't exist in .NET Core.

    An alternative is the DispatchProxy, which has a wonderful example here: http://www.c-sharpcorner.com/article/aspect-oriented-programming-in-c-sharp-using-dispatchproxy/.

    If we simplify the code, this is what we get:

    public class LoggingDecorator<T> : DispatchProxy
    {
        private T _decorated;
    
        protected override object Invoke(MethodInfo targetMethod, object[] args)
        {
            try
            {
                LogBefore(targetMethod, args);
    
                var result = targetMethod.Invoke(_decorated, args);
    
                LogAfter(targetMethod, args, result);
                return result;
            }
            catch (Exception ex) when (ex is TargetInvocationException)
            {
                LogException(ex.InnerException ?? ex, targetMethod);
                throw ex.InnerException ?? ex;
            }
        }
    
        public static T Create(T decorated)
        {
            object proxy = Create<T, LoggingDecorator<T>>();
            ((LoggingDecorator<T>)proxy).SetParameters(decorated);
    
            return (T)proxy;
        }
    
        private void SetParameters(T decorated)
        {
            if (decorated == null)
            {
                throw new ArgumentNullException(nameof(decorated));
            }
            _decorated = decorated;
        }
    
        private void LogException(Exception exception, MethodInfo methodInfo = null)
        {
            Console.WriteLine($"Class {_decorated.GetType().FullName}, Method {methodInfo.Name} threw exception:\n{exception}");
        }
    
        private void LogAfter(MethodInfo methodInfo, object[] args, object result)
        {
            Console.WriteLine($"Class {_decorated.GetType().FullName}, Method {methodInfo.Name} executed, Output: {result}");
        }
    
        private void LogBefore(MethodInfo methodInfo, object[] args)
        {
            Console.WriteLine($"Class {_decorated.GetType().FullName}, Method {methodInfo.Name} is executing");
        }
    }
    

    So if we have an example class Calculator with a corresponding interface (not shown here):

    public class Calculator : ICalculator
    {
        public int Add(int a, int b)
        {
            return a + b;
        }
    }
    

    we can simply use it like this

    static void Main(string[] args)
    {
        var decoratedCalculator = LoggingDecorator<ICalculator>.Create(new Calculator());
        decoratedCalculator.Add(3, 5);
        Console.ReadKey();
    }
    

    And you will get the desired logging.