RealProxy in dotnet core?

岁酱吖の 提交于 2019-12-17 22:27:10

问题


I'm working with the namespaces System.Runtime.Remoting.Proxies and System.Runtime.Remoting.Messaging for AOP in C#. I'm trying to port my application from .Net Framework 4.6 to dnxcore/dotnet core.

Intellisense says, that these two namespaces are not available with my framework-vesion (netcoreapp1.0 / dnxcore50). Any idea if these two namespaces will appear? or any idea how to get the AOP like with the RealProxy-class?

I don't want to use 3rd-party-libraries - I only want to use what .Net offers me.


回答1:


It looks like RealProxy won't come to .NET Core/Standard. In the issue, a Microsoft developer suggests DispatchProxy as an alternative.

Also, some existing AOP frameworks may support .NET Core already or in the future (as seen in the comments on the question).

An alternative is the DispatchProxy, which has a wonderful example here: http://www.c-sharpcorner.com/article/aspect-oriented-programming-in-c-sharp-using-dispatchproxy/.

If we simplify the code, this is what we get:

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

So if we have an example class Calculator with a corresponding interface (not shown here):

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

we can simply use it like this

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



回答2:


You can use either System.Reflection.DispatchProxy or your own simple decorator implementations. Check Decorator pattern page on Wikipedia for implementation examples.

Currently in .NET Core you can't use constructor injection with DispatchProxy. You have to use DispatchProxy.Create() factory method and property injection with explicit cast to proxy type that you want to use. For more information check DispachProxyTest.cs in .NET Core GitHub repository.

This is an example of a simple generic decorator that inherits 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;
    }
}

And it's usage:

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



回答3:


You can also use a combination of Autofac and DynamicProxy. This article has a nice introduction and samples on how to accomplish it.

AOP in .Net Core



来源:https://stackoverflow.com/questions/38467753/realproxy-in-dotnet-core

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!