Raz*_*zer 9 c# python design-patterns decorator
在python
可以实现function decorators
扩展功能和方法的行为.
特别是我正在将设备lib迁移python
到C#
.与设备的通信可能会产生错误,应该使用自定义异常重新启动.
在python
我会写这样的:
@device_error_wrapper("Device A", "Error while setting output voltage.")
def set_voltage(self, voltage):
"""
Safely set the output voltage of device.
"""
self.__handle.write(":source:voltage:level {0}".format(voltage))
Run Code Online (Sandbox Code Playgroud)
此方法调用将扩展为
try:
self.__handle.write(":source:voltage:level {0}".format(voltage))
except Error:
raise DeviceError("Error while setting output voltage.", "DeviceA")
Run Code Online (Sandbox Code Playgroud)
使用此模式,您可以轻松地包装和扩展方法,而无需try-except
在每个方法中编写每个子句.
是否可以使用C#
?实现类似的模式?
如果需要实现decorator(device_error_wrapper
),请告诉我们.
正如其他人所指出的那样,PostSharp等工具允许您在编译期间(实际上,之后)编织交叉逻辑.
另一种方法是在运行时执行此操作.一些IoC工具允许您定义拦截器,然后将拦截器添加到您的实现的代理类中.这听起来要复杂得多,所以我将展示一个基于Castle DynamicProxy的例子.
首先,您定义需要包装的类.
[Interceptor(typeof(SecurityInterceptor))]
public class OrderManagementService : IOrderManagementService
{
[RequiredPermission(Permissions.CanCreateOrder)]
public virtual Guid CreateOrder(string orderCode)
{
Order order = new Order(orderCode);
order.Save(order); // ActiveRecord-like implementation
return order.Id;
}
}
Run Code Online (Sandbox Code Playgroud)
RequiredPermission
在这里担任装饰师.类本身装饰有Interceptor
属性,指定接口方法调用的处理程序.这也可以放入配置中,因此它在课堂上是隐藏的.
拦截器实现包含装饰器逻辑
class SecurityInterceptor : IMethodInterceptor
{
public object Intercept(IMethodInvocation invocation, params object[] args)
{
MethodInfo method = invocation.Method;
if (method.IsDefined(typeof(RequiredPermission), true) // method has RequiredPermission attribute
&& GetRequiredPermission(method) != Context.Caller.Permission) {
throw new SecurityException("No permission!");
}
return invocation.Proceed(args);
}
private Permission GetRequiredPermission(MethodInfo method)
{
RequiredPermission attribute = (RequiredPermission)method.GetCustomAttributes(typeof(RequiredPermission), false)[0];
return attribute.Permission;
}
}
Run Code Online (Sandbox Code Playgroud)
但是有一些缺点:
您可以使用Aspect Oriented Programming实现类似的目标。我过去只使用过PostSharp,但它不是免费用于商业用途的。
还有其他 AOP 解决方案,您当然可以使用Mono.Cecil实现类似的功能,但需要做更多的工作。
Reza Ahmadi 写了一篇不错的介绍文章,称为使用 C# 和 PostSharp 的面向方面编程。它可以让您对预期的内容及其工作方式有足够的了解。