Autofac拦截不起作用

时间:2018-06-05 22:41:53

标签: autofac

我无法通过autofac进行拦截。我的.net核心应用程序中有以下设置:

// Logger created://

public class Logger : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        // Logging removed for now
        var watch = System.Diagnostics.Stopwatch.StartNew();  // Added break point here
        invocation.Proceed(); 
        watch.Stop();
        var executionTime = watch.ElapsedMilliseconds;
    }
}

//创建类://

[Intercept(typeof(Logger))]
public class ServiceProxy: ServiceInterface
{
    public User GetUser(String username, String password)
    {
        var service = ServiceHelper.GetODataClaimService();
        var query = from a in service.Users
                            select a;
        var dsq = query.ToDataServiceQuery<User>();
        var result = dsq.ToListSync<User>();
        var user = result.FirstOrDefault();
        return user;
    }
}

//界面创建://

public interface ServiceInterface
{
    User GetUser(String username, String password);
}

//拦截配置//

public class Interceptor
{
    public static void Configure()
    {
        var builder = new ContainerBuilder();
        builder.Register(a => new Logger());
        builder.RegisterType<ServiceProxy>().As<ServiceInterface>().EnableInterfaceInterceptors().InterceptedBy(typeof(Logger));  // Tried removing intercepted by
        var container = builder.Build();
        var worker = container.Resolve<ServiceInterface>();
        builder.Build()
    }
}

我在记录器中放置了一个断点,看它是否曾进入该代码块。 它永远不会。我在这里错过了什么? 我尝试了很多配置,但似乎没有任何工作。 另外 - 从应用程序启动调用Configure方法..

请告知。

2 个答案:

答案 0 :(得分:0)

使用您发布的代码,我无法重现您描述的问题。拦截器被击中,一切正常。

但是,我必须进行三次更改才能尝试。

  1. 我将ServiceInterface.GetUser方法切换为只返回一个字符串。我没有你的数据对象或任何东西。如果对整个问题不重要,我建议从问题中删除那些东西。
  2. 我删除了InterceptedBy(typeof(Logger))。属性不需要这些,但我确实看到了你试过的评论。
  3. 我从builder.Build()方法中删除了重复的Interceptor.Configure()。这实际上会在尝试第二次构建容器时引发异常。
  4. 项目#3关注我,因为这意味着repro可能会遗漏一些导致问题的东西(也许你在发布之前没有尝试过repro?)。

    无论如何,这是一个使用您的代码的完全正常的控制台应用程序:

        using Autofac;
        using Autofac.Extras.DynamicProxy;
        using Castle.DynamicProxy;
        using System;
    
        namespace InterfaceInterception
        {
            class Program
            {
                static void Main(string[] args)
                {
                    var builder = new ContainerBuilder();
                    builder.Register(a => new Logger());
                    builder.RegisterType<ServiceProxy>().As<ServiceInterface>().EnableInterfaceInterceptors();
                    var container = builder.Build();
                    var worker = container.Resolve<ServiceInterface>();
                    Console.WriteLine(worker.GetUser("", ""));
                    Console.ReadKey();
                }
            }
    
            public class Logger : IInterceptor
            {
                public void Intercept(IInvocation invocation)
                {
                    var watch = System.Diagnostics.Stopwatch.StartNew();
                    invocation.Proceed();
                    watch.Stop();
                    var executionTime = watch.ElapsedMilliseconds;
                    Console.WriteLine("Execution time: {0}", executionTime);
                }
            }
    
            [Intercept(typeof(Logger))]
            public class ServiceProxy : ServiceInterface
            {
                public string GetUser(String username, String password)
                {
                    return "a";
                }
            }
    
            public interface ServiceInterface
            {
                string GetUser(String username, String password);
            }
        }
    

    控制台输出如下:

    Execution time: 1
    a
    

    你可以在拦截器中放置一个断点,它会受到攻击。控制台输出也显示它被击中。所以...还有其他事情正在发生,可能在您的应用代码中,这会导致您看到的问题。这里的复制品看起来[基本上]很好。

答案 1 :(得分:0)

我在发布之后意识到,网上的所有示例都只显示正在创建的构建器并直接执行方法。我假设有类似于ContextBoundedObjects / Remote Services的拦截,但事实并非如此。为了使其工作,我不得不使用依赖注入将ServiceInterface注入到我的类的构造函数中。实际上,构建器拦截了这个并传入了Castle.Proxies.ServiceInterfaceProxy。

public class LoginController : Controller
{
    ServiceInterface proxy;

    public LoginController(ServiceInterface _proxy)
    {
        proxy = _proxy;
    }
}

这需要一些我在网上找到的示例中没有的其他内容:

  1. 包含Autofac依赖注入

    使用Autofac.Extensions.DependencyInjection;

  2. 确保Autofac包含在WebHostBuilder

     public class Program
    {
        public static void Main(string[] args)
        {
            var host = new WebHostBuilder()
                .UseKestrel()
                .ConfigureServices(services => services.AddAutofac())
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseIISIntegration()
                .UseStartup<Startup>()
                .Build();
            host.Run();
        }
    }
    
  3. 配置服务必须更改才能返回IServiceProvider

  4. 设置构建器时,请确保包含builder.Populate(services)

    public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
            services.AddKendo();
            services.AddDistributedMemoryCache();
            services.AddSession(options =>
            {
                options.IdleTimeout = TimeSpan.FromMinutes(Convert.ToInt32(Configuration["SessionTimeout"]));
                options.Cookie.HttpOnly = true;
            });
            return ConfigureProvider(services);
        }
    
        public IServiceProvider ConfigureProvider(IServiceCollection services)
        {
            var builder = new ContainerBuilder();
            builder.Populate(services);
            builder.Register(a => new LogInterception());
            builder.Register(a => new CircuitInterception());
            builder.RegisterType<ServiceProxy>().As<ServiceInterface>().EnableInterfaceInterceptors();
            Container = builder.Build();
            return new AutofacServiceProvider(this.Container);
        }