【问题标题】:Interception Using StructureMap 3.*使用 StructureMap 3.* 拦截
【发布时间】:2014-06-28 22:09:29
【问题描述】:

我已经使用 Castle.DynamicProxy 和 StructureMap 2.6 API 进行了拦截,但现在无法使用 StructureMap 3.0 进行拦截。谁能帮我找到更新的文档甚至演示?我发现的一切似乎都与旧版本有关。例如StructureMap.Interceptors.TypeInterceptor 接口等

【问题讨论】:

    标签: dependency-injection inversion-of-control ioc-container interception structuremap3


    【解决方案1】:

    哈哈哈!我他妈的做到了!方法如下:

    public class ServiceSingletonConvention : DefaultConventionScanner
    {
        public override void Process(Type type, Registry registry)
        {
            base.Process(type, registry);
    
            if (type.IsInterface || !type.Name.ToLower().EndsWith("service")) return;
    
            var pluginType = FindPluginType(type);
    
            var delegateType = typeof(Func<,>).MakeGenericType(pluginType, pluginType);
    
            // Create FuncInterceptor class with generic argument +
            var d1 = typeof(FuncInterceptor<>);
    
            Type[] typeArgs = { pluginType };
    
            var interceptorType = d1.MakeGenericType(typeArgs);
            // -
    
            // Create lambda expression for passing it to the FuncInterceptor constructor +
            var arg = Expression.Parameter(pluginType, "x");
    
            var method = GetType().GetMethod("GetProxy").MakeGenericMethod(pluginType);
    
            // Crate method calling expression
            var methodCall = Expression.Call(method, arg);
    
            // Create the lambda expression
            var lambda = Expression.Lambda(delegateType, methodCall, arg);
            // -
    
            // Create instance of the FuncInterceptor
            var interceptor = Activator.CreateInstance(interceptorType, lambda, "");
    
            registry.For(pluginType).Singleton().Use(type).InterceptWith(interceptor as IInterceptor);
        }
    
        public static T GetProxy<T>(object service)
        {
            var proxyGeneration = new ProxyGenerator();
    
            var result = proxyGeneration.CreateInterfaceProxyWithTarget(
               typeof(T),
               service,
               (Castle.DynamicProxy.IInterceptor)(new MyInterceptor())
               );
    
            return (T)result;
        }
    }
    

    这里的问题是 SM 3.* 允许拦截已知类型,即执行以下操作:

    expression.For<IService>().Use<Service>().InterceptWith(new FuncInterceptor<IService>(service => GetProxyFrom(service)));
    

    但是,如果您想在自定义扫描约定中包含拦截逻辑,您想拦截具有特定签名的所有类型实例(在我的例子中,类型名称以“服务”结尾)?

    这就是我使用 Expression API 和反射所完成的。

    另外,我在这里使用 Castle.DinamicProxy 为我的服务创建代理对象。

    希望其他人会觉得这很有帮助:)

    【讨论】:

      【解决方案2】:

      我发现任何新版本的最佳去处是直接访问源代码。

      如果写得好,那么它将包含测试用例。幸好结构图确实包含测试用例。

      您可以探索测试here

      与此同时,我已经编写了一个 Activator Interceptor 的示例,以及如何配置它。

      static void Main()
      {
          ObjectFactory.Configure(x =>
          {
              x.For<Form>().Use<Form1>()
                  .InterceptWith(new ActivatorInterceptor<Form1>(y =>  Form1Interceptor(y), "Test"));
          });
          Application.Run(ObjectFactory.GetInstance<Form>());
      
      }
      
      public static void Form1Interceptor(Form f)
      {
          //Sets the title of the form window to "Testing"
          f.Text = "Testing";
      }
      

      编辑:

      如何使用PoliciesExpression 使用“全局”过滤器

      [STAThread]
      static void Main()
      {
          ObjectFactory.Configure(x =>
          {
              x.Policies.Interceptors(new InterceptorPolicy<Form>(new FuncInterceptor<Form>(y => Intercept(y))));
          });
          Application.Run(ObjectFactory.GetInstance<Form>());
      }
      
      private static Form Intercept(Form form)
      {
          //Do the interception here
          form.Text = "Testing";
          return form;
      }
      

      【讨论】:

      • 非常感谢。但我正在寻找的是一种允许我使用 Castle Dynamic Proxy 拦截方法调用的方法。而且我还想将它用于多个接口,例如对于给定程序集中的所有服务。现在我正在使用我自己的约定扫描器,并想在其中添加拦截逻辑。像这样:registry.For(pluginType).Singleton().Use(type).Intercept(....等等
      • 使用 SM2 发布您的旧工作代码,也许我可以提供进一步的帮助。
      • 基本上我在 SM2 中通过调用 ConfigurationExpression.RegisterInterceptor 方法来做到这一点,这需要简单的 TypeInterceptor 实例。经过数小时的努力,我发现我想要的是类似于 FuncInterceptor 的东西,如果我只是想要对一种特定的插件类型进行拦截
      • 即而不是这样的:registry.For() .Use() .InterceptWith(new FuncInterceptor(blablabla));我想在 DefaultConventionScanner 中做同样的事情,即动态地,不知道确切的类型
      • 我看到这意味着编写新的 IInterceptor 的一些自定义实现,这将在 ToExpression 重载中起到作用。但是我对表达式的概念还不是很熟悉,并且必须努力奋斗。难道他们不能只添加简单的拦截方法,只需要一个简单的 lambda 表达式来调整插入的实例吗?呃……
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-22
      • 2012-12-07
      • 1970-01-01
      • 1970-01-01
      • 2012-01-03
      • 1970-01-01
      • 2012-08-18
      相关资源
      最近更新 更多