Autofac不拦截对类的调用

时间:2019-03-07 19:52:59

标签: asp.net-core autofac

我无法通过autofac截获对我班级的电话。 我已经修改了Program.cs文件,使其包含Autofac。 我已经修改了Startup.cs文件,使其包含ConfigureContainer。 调用该方法时,它将绕过Loggable属性中的Intercept方法。缺少什么?

public class Program
{
    public static void Main(string[] args)
    {
        var host = WebHost.CreateDefaultBuilder(args)
                          .UseKestrel()
                          .ConfigureServices(services => services.AddAutofac())
                          .UseStartup<Startup>().Build();
        host.Run();
    }
}

public class Startup
{
    public IConfiguration Configuration { get; private set; }

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public void ConfigureContainer(ContainerBuilder builder)
    {
        var helper = new StartupHelper();
        helper.Configure(builder, Configuration);
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddOData();
        services.AddMvc()
                .AddControllersAsServices();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        var name = "OData";
        var prefix = "OData";
        var builder = new ODataConventionModelBuilder();

        builder.EntitySet<DistributorParent>("DistributorParents")
               .EntityType
               .HasKey(a => a.DistparKey);

        app.UseMvc(routebuilder =>
        {
            routebuilder.Select()
                        .Expand()
                        .Filter()
                        .OrderBy()
                        .MaxTop(null)
                        .Count();
            routebuilder.MapODataServiceRoute(name, prefix, builder.GetEdmModel());
        });
    }
}

public class StartupHelper
{
    public ContainerBuilder Configure(ContainerBuilder builder, IConfiguration configuration = null)
    {
        builder.Register(a => configuration);
        builder.Register(a => new Loggable());
        builder.RegisterType<DistributorParentBusiness>()
               .As<IBusiness<DistributorParent>>()
               .EnableInterfaceInterceptors()
               .InterceptedBy(typeof(Loggable));
        return builder;
    }
}


[Loggable]
public class DistributorParentBusiness : IBusiness<DistributorParent>
{
    private IConfiguration Configuration;
    private String Connection;

    public DistributorParentBusiness(IConfiguration configuration)
    {
        Configuration = configuration;
        Connection = Configuration.GetConnectionString("CorpdbConnection");
    }

    public virtual DistributorParent Get(Int32 key)
    {
        var context = new CorpdbContext(Connection);
        var query = from a in context.DistributorParent
                    where a.DistparKey == key
                    select a;
        return query.FirstOrDefault();
    }

    public virtual IQueryable<DistributorParent> Get()
    {
        var context = new CorpdbContext(Connection);
        var query = from a in context.DistributorParent
                    select a;
        return query;
    }
}

2 个答案:

答案 0 :(得分:0)

这里有很多要解压的内容,而并非100%所需的信息。我会给您一些要看的东西,其中之一应该有所帮助。

您正在使用接口拦截器,因此将仅拦截接口方法。我不知道IBusiness<T>接口的外观(部分丢失的信息),所以我不知道不知道DistributorParentBusiness中的哪些方法是接口的一部分。如果您在界面中调用不是 的方法,则该方法将不会被拦截。

Loggable看起来像一个属性,但是需要实现IInterceptor我不知道Loggable是什么样,但是它必须实现{{1 }}(如果您正在使用它进行拦截)。它根本不是属性,这让我感到奇怪。它似乎没有做任何事情,因为它是以属性形式应用的。

The Autofac docs have examples of setting up interface injection.如果使用IInterceptor,则不使用属性。如果要使用属性,则必须为InterceptedBy(typeof(T)),如果要使用属性,则不要使用[Intercept(typeof(Logger))]。是/或,并且拦截器永远不是属性本身。

控制器是服务,但我不知道InterceptedBy(typeof(T))在哪里使用。同样,缺少信息。如果将其注入控制器中,它应该可以工作。我认为,如果您不添加controllers-as-services,它甚至应该可以工作。

您在其中计算所有路由的路由生成器调用很奇怪。不,这与问题无关,但是...正在对它们进行计数而不使用值?什么...呃...发生了什么事?

我要尝试的是为自己创建一个单元测试级别的副本。也就是说,仅在可以参与的单元测试中创建一个小的副本。确保首先正确连接接口拦截器。做一个超级简单,基本上是空的IBusiness<DistributorParent>实现;创建一个具有接口拦截功能的容器;手动解决IBusiness<DistributorParent>;在拦截器中设置断点;调用您希望被截获的方法,并查看断点是否被击中。或创建一个始终返回固定的已知值的拦截器,并在测试中使用该拦截器(如果未遇到断点的话),有时诸如“ Just My Code”之类的设置可能最终导致某些内容被跳过。

要点是,如果以上所有内容均无法解决问题,请在单元测试表格中创建一个真正的最小复制品,并确保其有效。如果可以的话,将其扩大一点-也许您在repro中使用了其他拦截器就可以了;尝试使用实际的IBusiness<DistributorParent>拦截器。它仍然有效吗?如果没有,也许是问题的拦截器。如果是这样,请扩大范围。最终,您将使整个工作正常进行,或者发现不起作用的地方。

如果您确实以最小的复制量使整个工作正常进行,那么问题可能是您没有意识到的。例如,repro中的代码是否与真实系统中的代码完全相同?有什么不同?努力使repro代码接近真实代码,并查看何时停止工作。

不过,我认为最低再现确实是您的关键。

对以后问题的建议-在创建问题代码时,请尝试使其成为我上面所述的用于故障排除的简单,微小的复制品。足以显示问题(并且可能由想要尝试的人进行编译),但仅此而已。

  • 包括所有正在使用的类和接口定义。例如LoggableLoggable
  • 删除不需要的内容。例如,IBusiness<T>调用中的路由配置不相关。
  • 尝试简化间接性和复杂性。可以将app.UseMvc()中的代码内联到StartupHelper方法中,以使回答问题的人们更容易阅读和理解。

答案 1 :(得分:0)

问题很傻。我是手动创建类,而不使用di。因此,这些方法不会被拦截。另外,原始设置试图拦截api控制器,并且这些方法不是虚拟的。只需进行少量配置更改即可注入IBusiness和voila,它确实有效...