web-dev-qa-db-fra.com

AOP dans le noyau Dotnet: proxy dynamique avec proxy réel dans le noyau Dotnet

Je migre mon application de .Net Framework 4.5.1 vers Dot Net Core. J'utilisais RealProxy Class pour enregistrer les informations et paramètres utilisateur sur BeforeExecute et AfterExecute (comme ceci lien )

Maintenant, il semble qu'il n'y ait rien de tel dans Dot core.Plus je ne veux pas utiliser de tiers.J'ai trouvé cela link qui utilise Actionfilter mais il ne fera pas le travail.

ma question est Comment puis-je implémenter Dynamic Proxy dans Dot net Core? Existe-t-il une alternative pour RealProxy Class?

20
Pouya Samie

Comme je l'ai déjà répondu dans RealProxy dans dotnet core? , RealProxy n'existe pas dans .NET Core.

Une alternative est le DispatchProxy, qui a un merveilleux exemple ici: http://www.c-sharpcorner.com/article/aspect-oriented-programming-in-c-sharp-using-dispatchproxy/ .

Si nous simplifions le code, voici ce que nous obtenons:

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

Donc, si nous avons un exemple de classe Calculator avec une interface correspondante (non représentée ici):

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

on peut simplement l'utiliser comme ça

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

Et vous obtiendrez la journalisation souhaitée.

7
CommonGuy