【问题标题】:Autofac Interception Not WorkingAutofac拦截不起作用
【发布时间】:2018-06-05 22:41:52
【问题描述】:

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

// 记录器创建: //

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 方法是从应用程序启动中调用的。

请指教。

【问题讨论】:

    标签: autofac


    【解决方案1】:

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

    但是,我必须进行三处更改才能试用。

    1. 我将ServiceInterface.GetUser 方法切换为只返回一个字符串。我没有你的数据对象或任何东西。如果对整个问题不重要,我建议从问题中的重现中删除这些内容。
    2. 我删除了InterceptedBy(typeof(Logger))。属性不需要这样做,但我确实看到评论说您尝试过。
    3. 我从Interceptor.Configure() 方法中删除了重复的builder.Build()。这实际上会在尝试第二次构建容器时引发异常。

    第 3 项与我有关,因为它意味着复制品可能遗漏了一些导致问题的东西(也许您在发布之前没有尝试过复制品?)。

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

        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
    

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

    【讨论】:

      【解决方案2】:

      我在发布此内容后意识到,网络上的所有示例都只是显示了正在创建的构建器并直接执行一个方法。我假设发生了类似于 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);
            }
        

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-04-29
        • 2018-01-07
        • 2017-09-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多