Mat*_*ger 34 c# aop .net-core dnx
我正在使用命名空间System.Runtime.Remoting.Proxies和System.Runtime.Remoting.MessagingC#中的AOP.我正在尝试将我的应用程序从.Net Framework 4.6移植到dnxcore/dotnet核心.
Intellisense说,这两个命名空间不适用于我的framework-vesion(netcoreapp1.0/dnxcore50).知道这两个命名空间是否会出现?或者任何想法如何使用RealProxy-class 获得AOP ?
我不想使用第三方库 - 我只想使用.Net提供给我的东西.
Com*_*Guy 35
看起来RealProxy不会出现在.NET Core/Standard中.在该问题中,Microsoft开发人员建议将DispatchProxy作为替代方案.
此外,一些现有的AOP框架可能已经或将来支持.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");
}
}
Run Code Online (Sandbox Code Playgroud)
因此,如果我们有一个Calculator带有相应接口的示例类(此处未显示):
public class Calculator : ICalculator
{
public int Add(int a, int b)
{
return a + b;
}
}
Run Code Online (Sandbox Code Playgroud)
我们可以像这样简单地使用它
static void Main(string[] args)
{
var decoratedCalculator = LoggingDecorator<ICalculator>.Create(new Calculator());
decoratedCalculator.Add(3, 5);
Console.ReadKey();
}
Run Code Online (Sandbox Code Playgroud)
您可以使用任一个System.Reflection.DispatchProxy或您自己的简单装饰器实现.检查Wikipedia上的Decorator模式页面以获取实现示例.
目前在.NET Core中,您无法使用构造函数注入DispatchProxy.您必须使用DispatchProxy.Create()工厂方法和属性注入以及要使用的显式强制转换为代理类型.有关更多信息,请查看.NET Core GitHub存储库中的DispachProxyTest.cs.
这是一个简单的通用装饰器的例子,它继承了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;
}
}
Run Code Online (Sandbox Code Playgroud)
它的用法:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6110 次 |
| 最近记录: |