RealProxy dans dotnet core?

Je travaille avec les espaces de noms System.Runtime.Remoting.Proxies et System.Runtime.Remoting.Messaging pour AOP en C#. J'essaie de porter mon application de. NET Framework 4.6 vers dnxcore / dotnet core.

Intellisense dit que ces deux espaces de noms ne sont pas disponibles avec mon framework-vesion (netcoreapp1. 0 / dnxcore50). Une idée si ces deux espaces de noms apparaîtront? ou une idée de comment obtenir L'AOP comme avec la classe RealProxy?

Je ne veux pas utiliser de bibliothèques tierces - je veux seulement utiliser ce que. NET m'offre.

24
demandé sur Matthias Burger 2016-07-19 23:18:37

3 réponses

Il semble que RealProxy ne viendra pas à.net Core/Standard. Dans le numéro, un développeur Microsoft suggère DispatchProxy comme alternative.

En outre, certains frameworks AOP existants peuvent prendre en charge. net Core déjà ou à l'avenir (comme on le voit dans les commentaires sur la question).

Une alternative est le DispatchProxy, qui a un exemple merveilleux 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;
    }
}

, Nous pouvons simplement l'utiliser comme ceci

static void Main(string[] args)
{
    var decoratedCalculator = LoggingDecorator<ICalculator>.Create(new Calculator());
    decoratedCalculator.Add(3, 5);
    Console.ReadKey();
}
21
répondu CommonGuy 2018-01-14 16:02:44

Vous pouvez utiliser System.Reflection.DispatchProxy ou vos propres implémentations de décorateur simples. Vérifiez la page Decorator pattern sur Wikipedia pour des exemples d'implémentation.

Actuellement dans. net Core, vous ne pouvez pas utiliser l'injection constructeur avec DispatchProxy. Vous devez utiliser la méthode d'usine DispatchProxy.Create() et l'injection de propriétés avec une conversion explicite en type proxy que vous souhaitez utiliser. Pour plus d'informations, consultez DispachProxyTest.cs dans le référentiel. net Core GitHub.

Ceci est un exemple d'un simple générique décorateur qui hérite de DispatchProxy:

class GenericDecorator : DispatchProxy
{
    public object Wrapped { get; set; }
    public Action<MethodInfo, object[]> Start { get; set; }
    public Action<MethodInfo, object[], object> End { get; set; }
    protected override object Invoke(MethodInfo targetMethod, object[] args)
    {
        Start?.Invoke(targetMethod, args);
        object result = targetMethod.Invoke(Wrapped, args);
        End?.Invoke(targetMethod, args, result);
        return result;
    }
}

Et son utilisation:

class Program
{
    static void Main(string[] args)
    {
        IEcho toWrap = new EchoImpl();
        IEcho decorator = DispatchProxy.Create<IEcho, GenericDecorator>();
        ((GenericDecorator)decorator).Wrapped = toWrap;
        ((GenericDecorator)decorator).Start = (tm, a) => Console.WriteLine($"{tm.Name}({string.Join(',', a)}) is started");
        ((GenericDecorator)decorator).End = (tm, a, r) => Console.WriteLine($"{tm.Name}({string.Join(',', a)}) is ended with result {r}");
        string result = decorator.Echo("Hello");
    }

    class EchoImpl : IEcho
    {
        public string Echo(string message) => message;
    }

    interface IEcho
    {
        string Echo(string message);
    }
}
5
répondu Leonid Vasilev 2018-01-12 12:19:58

Vous pouvez également utiliser une combinaison D'Autofac et de DynamicProxy. Cet article a une belle introduction et des échantillons sur la façon de l'accomplir.

AOP dans .Net De Base

1
répondu Carlos Blanco 2018-02-14 19:47:38