C# 在C中实现方法修饰符#
在C# 在C中实现方法修饰符#,c#,python,design-patterns,decorator,C#,Python,Design Patterns,Decorator,在python中,可以实现function decorators来扩展函数和方法的行为 特别是,我正在将设备库从python迁移到C。与设备的通信可能会产生错误,这些错误应通过自定义异常重新确认 在python中,我会这样写: @device_error_wrapper("Device A", "Error while setting output voltage.") def set_voltage(self, voltage): """ Safely set the o
python
中,可以实现function decorators
来扩展函数和方法的行为
特别是,我正在将设备库从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))
此方法调用将扩展到
try:
self.__handle.write(":source:voltage:level {0}".format(voltage))
except Error:
raise DeviceError("Error while setting output voltage.", "DeviceA")
使用此模式,您可以轻松地包装和扩展方法,而无需在每个方法中编写每个try-except
子句
是否可以使用C
实现类似的模式
如果需要decorator(
device\u error\u wrapper
)的实现,请告知。您可以使用。我只在过去使用过,但它不是免费的商业用途
还有其他AOP解决方案,您当然可以使用它实现类似的功能,但这需要更多的工作
雷扎·艾哈迈迪写了一篇很好的介绍文章,名为。它可以让您清楚地了解所期望的内容以及它是如何工作的。在C中实现这样的装饰器没有简单的方法-默认情况下只是描述性的。然而,有些项目扩展了C#编译器或运行时,因此您可以实际使用它。我认为最好的是。使用它,您可以定义这样的方法decorator(“通常是方面”),并在编译过程中按照需要包装该方法
我也看到过通过装饰类实际包装类来实现这一点,但这需要大量的工作,我不认为这可以用一种真正通用的方式来完成。维基百科在中显示了这一点,正如其他人提到的,您正在寻找AOP。PostSharp是一个很好的编译后解决方案,但它是一个运行时AOP解决方案。正如其他人所指出的,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;
}
}
RequiredPermission
在这里充当装饰者。类本身用拦截器属性修饰,该属性指定接口方法调用的处理程序。这也可以放入配置中,因此它对类是隐藏的
拦截器实现包含decorator逻辑
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;
}
}
但也有一些缺点:
- 使用DynamicProxy,您只能包装接口和虚拟方法
- 您需要通过IoC容器而不是直接实例化对象(如果您已经使用IoC容器,这不是问题)
我知道的另一种选择是使用代理(本答案中的示例),或者您可以尝试postsharp(在其中一个答案中也提到)。如果真的可以将属性用作方法装饰器,我不知道(我对此表示怀疑,但我打赌有人会为您解答这个问题)。与Mono.Cecil相关。你可以看看西蒙·克洛普的福迪。这是一个很好的小插件,可以帮助您将预构建的方面编织到代码中。它还包含一个模板来帮助您构建自己的方面。