如何从 Castle.DynamicProxy 中的 ProxyGenerationHook 访问自定义方法属性

Posted

技术标签:

【中文标题】如何从 Castle.DynamicProxy 中的 ProxyGenerationHook 访问自定义方法属性【英文标题】:How to access custom method attributes from ProxyGenerationHook in Castle.DynamicProxy 【发布时间】:2021-03-13 15:42:58 【问题描述】:

我正在使用 Castle.DynamicProxy (Castle.Core 4.4.0) 在 .NET 中实现 Interceptor 机制。我正在按照本教程选择要拦截的方法:https://kozmic.net/2009/01/17/castle-dynamic-proxy-tutorial-part-iii-selecting-which-methods-to/

本文中给出了一个关于“选择拦截哪些方法”的例子:

public class FreezableProxyGenerationHook:IProxyGenerationHook

    public bool ShouldInterceptMethod(Type type, MethodInfo memberInfo)
    
        return !memberInfo.Name.StartsWith("get_", StringComparison.Ordinal);
    
    //implementing other methods... 

根据这篇文章,我实现了ShouldInterceptMethod,如下所示,但我无法访问该方法的自定义属性。

public class ProductServiceProxyGenerationHook : IProxyGenerationHook

    public void MethodsInspected()
    
    
    public void NonProxyableMemberNotification(Type type, MemberInfo memberInfo)
    
    

    public bool ShouldInterceptMethod(Type type, MethodInfo methodInfo)
    
        //return methodInfo.CustomAttributes.Any(a => a.GetType() == typeof(UseInterceptorAttribute));
        return methodInfo.CustomAttributes.Count() > 0;
    

这是我要拦截的方法:

[UseInterceptor]
public Product AOP_Get(string serialNumber)

    throw new NotImplementedException();      

这是我的自定义属性:

[System.AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
sealed class UseInterceptorAttribute : Attribute

    public UseInterceptorAttribute()
    
    

当为AOP_Get 方法调用ShouldInterceptMethod 时,局部变量methodInfo 上没有任何自定义属性。结果ShouldInterceptMethod 返回false。但是当我从AOP_Get 方法体中检查时,我可以访问自定义属性,如下所示:

如何在ShouldInterceptMethod 方法中访问自定义属性?

【问题讨论】:

你能上传一个最小的例子到 github,这样我就可以摆弄它了吗? @Simon:我将最小示例上传到 GitHub:link 这个solution 是可用的,但我们仍在拦截所有方法。 【参考方案1】:

我在 interface 方法中使用UseInterceptorAttribute 解决了这个问题。因为拦截器正在为接口启用:

//autofac
var proxyGenerationOptions = new ProxyGenerationOptions(new ProductServiceProxyGenerationHook());

builder.RegisterType<ProductService>()
                .As<IProductService>()
                .EnableInterfaceInterceptors(proxyGenerationOptions)
                .InterceptedBy(typeof(LoggingInterceptor));

解决办法:

public interface IProductService

    Product Get(string productNumber, string serialNumber);

    bool Create(string productNumber, string serialNumber);

    [UseInterceptor]
    Product AOP_Get(string productNumber, string serialNumber);


public class ProductService : IProductService
 
    public Product AOP_Get(string productNumber, string serialNumber)
    
        var m = GetType().GetMethod("AOP_Get");
        return null;
    

    public bool Create(string productNumber, string serialNumber)
    
        return true;
    

    public Product Get(string productNumber, string serialNumber)
    
        return new Product
        
            Id = 5,
            ProductNumber = "testPN",
            SerialNumber = "testSN"
        ;
    

    public class ProductServiceProxyGenerationHook : IProxyGenerationHook
    
        public void MethodsInspected()
        
        

        public void NonProxyableMemberNotification(Type type, MemberInfo memberInfo)
        
        

        public bool ShouldInterceptMethod(Type type, MethodInfo methodInfo)
        
            return methodInfo
                .CustomAttributes
                .Any(a => a.AttributeType == typeof(UseInterceptorAttribute));
        
    

【讨论】:

以上是关于如何从 Castle.DynamicProxy 中的 ProxyGenerationHook 访问自定义方法属性的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中使用 Castle.DynamicProxy 对数组进行排序

Castle.DynamicProxy拦截器

Castle DynamicProxy

castle.dynamicProxy学习笔记

Autofac + Castle DynamicProxy:拦截器的顺序

.NET Core 默认依赖注入与 Castle DynamicProxy