.NETCoreでのアスペクト指向メモ
この記事の前提
備忘録的に残すために記述したものです。
.NETCoreでのアスペクト指向
.NET CoreではRealProxyクラスがない。
代わりにDispatchProxyクラスを使う。
サンプルソース
AkProxy.cs
プロキシクラスです。
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
ロジッククラスです。
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
ロジッククラスのメソッドの呼び出し処理です。(テストメソッド)
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)
{
}
}
}
}