Implement method decorators in C#

前端 未结 4 1433
忘了有多久
忘了有多久 2020-12-31 12:48

In python is possible to implement function decorators to extend the behavior of functions and methods.

In particular I\'m migrating a devi

相关标签:
4条回答
  • As others have pointed out, tools like PostSharp allow you to weave in the cross cutting logic during (actually, after) compilation.

    The alternative is to do it in runtime. Some IoC tools allow you to define the interceptors which are then added to proxy classes to your implementation. This sounds much more complex then it really is, so I will show an example based on Castle DynamicProxy.

    First you define your class which needs to be wrapped.

    [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 serves as a decorator here. The class itself is adorned with Interceptor attribute specifying the handler for the interface method calls. This can also be put into configuration, so it is hidden from the class.

    The interceptor implementation contains the decorator logic

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

    There are some drawbacks, however:

    • with DynamicProxy you can only wrap interfaces and virtual methods.
    • you need to instantiate the object via IoC container and not directly (which is not a problem if you already use IoC container)
    0 讨论(0)
  • 2020-12-31 13:15

    You can achieve something similar using Aspect Oriented Programming. I've only used PostSharp in the past but it's not free for commercial use though.

    There are other AOP solutions out there and you can certainly achieve something similar using Mono.Cecil, but it would require more work.

    Reza Ahmadi wrote a nice little introduction article called Aspect Oriented Programming Using C# and PostSharp. It can give you a clear enough idea of what to expect and how it works.

    0 讨论(0)
  • 2020-12-31 13:19

    As others have mentioned you are looking for AOP. PostSharp is a good post compile solution, but Castle DynamicProxy is a runtime AOP solution.

    0 讨论(0)
  • 2020-12-31 13:29

    There's no easy way to implement such decorators in C# - custom Attributes are by default only descriptive. There are however projects that extend C# compiler or runtime so that you can actually use this. I think the best one is PostSharp. With it you can define such method decorator ("aspect" in general) and the method gets wrapped during compilation like you need.

    I've also seen this implemented by actually wrapping your classes by decorator classes, but that's a lot of work and I don't think it can be done in a really general way. Wikipedia shows this in Decorator Pattern article

    0 讨论(0)
提交回复
热议问题