.NETCoreでのアスペクト指向メモ

# .NETCoreでのアスペクト指向メモ
## この記事の前提
備忘録的に残すために記述したものです。

## .NETCoreでのアスペクト指向
.NET CoreではRealProxyクラスがない。<br>
代わりにDispatchProxyクラスを使う。<br>

## サンプルソース
### AkProxy.cs
プロキシクラスです。

```c#:AkProxy.cs
using System;
using System.Diagnostics;
using System.Reflection;

namespace Ak.Sample.Core.Aspect
{
    public class AkProxy<T> : DispatchProxy
    {
        private T _instance;

        public static T Create(T instance)
        {
            object proxy = Create<T, AkProxy<T>>();
            ((AkProxy<T>)proxy).SetParameters(instance);

            return (T)proxy;
        }

        protected void SetParameters(T instance)
        {
            if (instance == null)
            {
                throw new ArgumentNullException(nameof(instance));
            }
            _instance = instance;
        }

        protected override object Invoke(MethodInfo targetMethod, object[] args)
        {
            Guid msgId = Guid.NewGuid();
            try
            {
                BeforeProcess(msgId, targetMethod, args);
                var result = targetMethod.Invoke(_instance, args);
                AfterProcess(msgId, targetMethod, args, result);

                return result;
            }
            catch (Exception ex) when (ex is TargetInvocationException)
            {
                ExceptionProcess(msgId, targetMethod, args, ex);
                throw ex.InnerException ?? ex;
            }
        }

        protected void BeforeProcess(Guid msgId, MethodInfo targetMethod, object[] args)
        {
            Console.WriteLine($"[{msgId.ToString()}][Method：{targetMethod.Name}] 処理を実行します。");
        }

        protected void AfterProcess(Guid msgId, MethodInfo targetMethod, object[] args, object result)
        {
            Console.WriteLine($"[{msgId.ToString()}][Method：{targetMethod.Name}] 処理が正常終了しました。");
        }

        protected void ExceptionProcess(Guid msgId, MethodInfo targetMethod, object[] args, Exception ex)
        {
            Console.WriteLine($"[{msgId.ToString()}][Method：{targetMethod.Name}] 例外が発生しました。");
            Console.WriteLine($"[{ex.ToString()}]");
        }
    }
}
```

### MyClass.cs
ロジッククラスです。

```C#:MyClass.cs
using System;
using System.Collections.Generic;
using System.Text;

namespace Ak.Sample.Core.Aspect.Test.SampleClass
{
    public interface IMyClass
    {
        int Sum(int a, int b);
        int Quotient(int a, int b);
    }

    public class MyClass : IMyClass
    {
        public int Sum(int a ,int b)
        {
            return a + b;
        }

        public int Quotient(int a, int b)
        {
            return a / b;
        }
    }
}
```

### UnitTest1.cs
ロジッククラスのメソッドの呼び出し処理です。（テストメソッド）

```c#:UnitTest1.cs
using Ak.Sample.Core.Aspect.Test.SampleClass;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.IO;
using System.Text;

namespace Ak.Sample.Core.Aspect.Test
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            IMyClass cls = AkProxy<IMyClass>.Create(new MyClass());
            Console.WriteLine(cls.Sum(1,2));
        }

        [TestMethod]
        public void TestMethod2()
        {
            try
            {
                IMyClass cls = AkProxy<IMyClass>.Create(new MyClass());
                Console.WriteLine(cls.Quotient(2, 0));
                Assert.Fail();
            }
            catch (Exception)
            {
            }
        }
    }
}

```