使用 StructureMap 3.* 拦截

Posted

技术标签:

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

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

【问题讨论】:

【参考方案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 表达式来调整插入的实例吗?呃……

以上是关于使用 StructureMap 3.* 拦截的主要内容,如果未能解决你的问题,请参考以下文章

使用 PetaPoco 与 StructureMap 的共享连接

抽象类是不是像接口一样与 StructureMap 一起使用?

DI 依赖注入之StructureMap框架

Structuremap 是不是支持开箱即用的 Lazy?

告诉 StructureMap 使用特定的构造函数

获取使用StructureMap从基类继承的唯一类型实例