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

How to access custom method attributes from ProxyGenerationHook in Castle.DynamicProxy

我正在使用 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 returns false。但是当我从 AOP_Get 方法体中检查时,我可以像下面这样访问自定义属性:

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

我在 接口 方法中使用 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));
        }
    }
}