web-dev-qa-db-ja.com

DotnetコアのAOP:Dotnetコアのリアルプロキシを使用した動的プロキシ

アプリケーションを.Net Framework 4.5.1からDot Net Coreに移行しています。私は RealProxy BeforeExecuteとAfterExecuteでユーザー情報とパラメーターをログに記録するためのクラスを使用していました(このように link

今、ドットコアにはそのようなものはないようです。加えて、サードパーティを使用したくありません。 link がActionfilterを使用していることがわかりましたが、機能しません。

私の質問はDot net Coreに動的プロキシを実装するにはどうすればよいですか?RealProxyクラスの代替はありますか?

20
Pouya Samie

RealProxy in dotnet core? ですでに回答したように、RealProxyは.NET Coreには存在しません。

別の方法はDispatchProxyで、ここに素晴らしい例があります: http://www.c-sharpcorner.com/article/aspect-oriented-programming-in-c-sharp-using- dispatchproxy /

コードを簡略化すると、次のようになります。

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");
    }
}

したがって、対応するインターフェースを備えたサンプルクラスCalculatorがある場合(ここには表示されていません):

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

このように使用できます

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

そして、必要なログを取得します。

7
CommonGuy