c# - 温莎城堡 : Changes for factories and interceptors in 3. 1?

标签 c# castle-windsor castle-dynamicproxy windsor-facilities

以下代码在 CaSTLe.Windsor 2.5.3 中按原样通过,但在升级到 3.1.0 后失败

异常是 InvalidProxyConstructorArgumentsException,它指出“无法实例化类的代理:Test。找不到无参数构造函数。”

    static void Main(string[] args)
    {
        var container = new WindsorContainer();
        container.Register(Component.For<Interceptor>(),
                           Component.For<Test>().UsingFactoryMethod(() => new Test(""))
                                                .Interceptors<Interceptor>());

        var test = container.Resolve<Test>(); //THROWS IN 3.1.0
    }
}

public class Test
{
    public readonly string S;

    public Test(string s)
    {
        S = s;
    }
}

public class Interceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        invocation.Proceed();
    }
}

在我的真实代码中,测试是一个 MongoDatabase,它是使用工厂方法构建并注入(inject)到存储库中的。

在我的实际代码中,我还使用 AbstractFacility 的继承者来注册拦截器。这样我就不必为每个组件注册拦截器。两种形式的拦截器使用似乎在以后的解析中以相同的方式工作/失败(在 2.5.3/3.1.0 中)。以下是该设施的简化版本,供引用:

public class Facility : AbstractFacility
{
    protected override void Init() { Kernel.ComponentRegistered += KernelComponentRegistered; }

    static void KernelComponentRegistered(string key, IHandler handler)
    {
        if (typeof(IInterceptor).IsAssignableFrom(handler.ComponentModel.Implementation)) return;
        handler.ComponentModel.Interceptors.AddIfNotInCollection(InterceptorReference.ForKey("SomeInterceptor"));
    }
}

我查看了 CaSTLe.Windsor 源代码,抛出的代码期望在给定的类周围包装一个代理,这就是它寻找无参数构造函数的原因。然而,在 2.5.3 中,我认为代理生成代码从未被执行,并且容器解析(在我看来正确)为 Test/MongoDatabase 的非代理版本

我猜有两个问题: 1)什么改变了? 2)如何在不为工厂方法解析的对象生成代理的情况下保留拦截器注册?或者我猜想如何使用组件的工厂方法生成代理......

最佳答案

在 2.5.3 中,Windsor 似乎默默地未能应用拦截器。在 3.1.0 中,当 Windsor 无法将拦截器应用于您已注册的类型时,它会引发异常。 Windsor 使用其动态代理库通过生成您请求的实例的代理来支持拦截器 (AOP)。因此,这两个版本的问题是您提供的类无法转换为动态代理,因为它没有无参数构造函数。我认为 3.1.0 中的行为更正确,因为如果您期望应用拦截器,那么找出问题所在会更加困难。

如果您想维持 2.5.3 中的行为,在该行为中它会默默地失败,只需在您的设施中注册拦截器之前添加一个检查以查看该类型是否可以被代理。可能有更好的方法,但这是我想到的:

try
{
    ProxyGenerator generator = new ProxyGenerator();
    generator.CreateClassProxy(handler.ComponentModel.Implementation);
    handler.ComponentModel.Interceptors.AddIfNotInCollection(InterceptorReference.ForType<MyInterceptor>());
}
catch {}

从很多方面来看,这都是糟糕的代码,但它会重新创建您习惯的行为。只是要小心,当您确实想要拦截器打开一个不同的类并且正在努力找出为什么它没有被调用时,它不会让您陷入困境。

关于c# - 温莎城堡 : Changes for factories and interceptors in 3. 1?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12636311/

相关文章:

c# - 基于字符串选择多个属性的值

c# - 在不丢失 pictureBox 的情况下处理 pictureBox 图像

c# - 在 .net windows 应用程序中使用 log4net

asp.net-mvc - Automapper 和 Windsor 的问题

c# - 用 IoC (CaSTLe Windsor) 替换以下代码

aop - Autofac + CaSTLe 动态代理 : Order of interceptors

C# Null 条件运算符替代方案(条件赋值)?

c# - 托管扩展框架、拦截和动态代理

c# - 动态转换为通用类型

c# - 将 Windsor CaSTLe 注入(inject)的依赖项传递给并行线程 - Dispose() 问题