Skip to content

当调用未被代理的方法且类的访问级别不是 public 时出错 #274

Open
@devenliu

Description

@devenliu

代码

/*********************
* MyWeb.csproj
**********************/
using AspectCore.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

namespace MyWeb
{
    // 启动类
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .UseServiceProviderFactory(new DynamicProxyServiceProviderFactory())  // 替换 DI 工厂
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }

    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.ConfigureDynamicProxy(config => 
            {
                // 注册全局拦截器(只拦截被打了标记的方法)
                config.Interceptors.AddTyped<TransactionalInterceptorAttribute>((MethodInfo method) => method.GetCustomAttribute<TransactionFlagAttribute>() != null);
            })
        }
    }
}

/*********************
* MyLib.csproj
**********************/
// 定义标记
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class TransactionFlagAttribute: Attribute
{

}

// 定义拦截器
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class TransactionInterceptorAttribute : AbstractInterceptorAttribute
{
    public override async Task Invoke(AspectContext context, AspectDelegate next)
    {
        // 启用事务...
        await next(context);
        // 提交事务...
    }
}

// 定义服务
public interface ICustomService
{
    // 给需要被代理的方法打上标记
    [TransactionFlag]
    void Todo1();

    //  这是不需要被代理的方法
    void Todo2();
}

// 服务的实现类,访问级别“程序集内部可见”
internal class MyInternalCustomService: ICustomService
{
    // 实现服务方法1
    public void Todo1()
    {
        //.....
    }

    // 实现服务方法2
    public void Todo1()
    {
        //.....
    }
}

重现

用例1:

  1. 通过构造函数获取 ICustomService 的实例
  2. 调用 ICustomService.Todo1()
  3. 结果:正确运行

用例2(导致了错误):

  1. 通过构造函数获取 ICustomService 的实例
  2. 调用 ICustomService.Todo2()
  3. 结果:无法访问方法,报错 System.MethodAccessException

问题

  1. 这是一个 bug 吗?
  2. 是我的用法不对吗?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions