Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 温莎城堡:3.1中工厂和拦截器的变化?_C#_Castle Windsor_Castle Dynamicproxy_Windsor Facilities - Fatal编程技术网

C# 温莎城堡:3.1中工厂和拦截器的变化?

C# 温莎城堡:3.1中工厂和拦截器的变化?,c#,castle-windsor,castle-dynamicproxy,windsor-facilities,C#,Castle Windsor,Castle Dynamicproxy,Windsor Facilities,以下代码与Castle.Windsor 2.5.3一样通过,但升级到3.1.0后失败 异常是InvalidProxyConstructorArgumentsException,它声明“无法实例化类的代理:Test。找不到无参数构造函数。” 我查看了Castle.Windsor源代码,抛出的代码希望在给定的类周围包装一个代理,这就是为什么它要寻找一个无参数构造函数。然而,在2.5.3中,我认为代理生成代码从未执行过,容器解析为(在我看来是正确的)非代理版本的Test/MongoDatabase 所

以下代码与Castle.Windsor 2.5.3一样通过,但升级到3.1.0后失败

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

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

所以我想有两个问题: 1) 发生了什么变化?
2) 如何保持拦截器注册,而不为工厂方法解析的对象生成代理?或者我猜如何使用组件的工厂方法生成代理…

Stefan让我走上了正确的轨道。拦截器没有被分配到2.5.3中测试的事实是一个伪装成bug的bug/特性。3.1.0的行为更加正确,并迫使您明确表示希望拦截器位于什么位置。由于我的实际代码涉及一个设施,下面是解决该问题的解决方案:

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

    static readonly List<Type> TypesNotToIntercept = new List<Type>
    {
        typeof(IInterceptor),   //Don't intercept Interceptors
        typeof(MulticastDelegate),  //Func<> and the like
        typeof(LateBoundComponent), //Resolved with a factory, such as MongoDatabase
    };

    static void KernelComponentRegistered(string key, IHandler handler)
    {
        if (TypesNotToIntercept.Any(type => type.IsAssignableFrom(implementation));
            return;
        handler.ComponentModel.Interceptors.AddIfNotInCollection(InterceptorReference.ForKey("SomeInterceptor"));
    }
}
公共类设施:AbstractFacility
{
受保护的重写void Init(){Kernel.ComponentRegistered+=KernelComponentRegistered;}
静态只读列表类型NotIntercept=新列表
{
typeof(IInterceptor),//不拦截拦截器
typeof(MulticastDelegate),//Func等
typeof(LateBoundComponent),//使用工厂解析,例如MongoDatabase
};
静态void KernelComponentRegistered(字符串键,IHandler处理程序)
{
if(typesnotintercept.Any(type=>type.IsAssignableFrom(实现));
返回;
handler.ComponentModel.Interceptors.AddIfNotInCollection(InterceptorReference.ForKey(“SomeInterceptor”);
}
}

在2.5.3中,Windsor似乎在静默中无法应用拦截器。在3.1.0中,Windsor在无法将拦截器应用于您注册的类型时引发异常。Windsor使用其动态代理库支持拦截器(AOP)通过生成你所请求的实例的代理,所以两个版本中的问题是,你给它的类不能变成动态代理,因为它没有一个无ARG构造函数。我认为3.1.0中的行为更正确,因为如果你预期应用了拦截器,那么它将是一个很大的问题。We’我们很难找出问题所在

如果您想保持2.5.3中的行为,在该行为以静默方式失败时,只需在您的设施中注册拦截器之前添加一个检查,看看该类型是否可以被代理。这样做可能更好,但我想到了以下几点:

try
{
    ProxyGenerator generator = new ProxyGenerator();
    generator.CreateClassProxy(handler.ComponentModel.Implementation);
    handler.ComponentModel.Interceptors.AddIfNotInCollection(InterceptorReference.ForType<MyInterceptor>());
}
catch {}
试试看
{
ProxyGenerator=新的ProxyGenerator();
CreateClassProxy(handler.ComponentModel.Implementation);
handler.ComponentModel.Interceptors.AddifyNotInCollection(InterceptorReference.ForType());
}
捕获{}

这在很多方面都是很糟糕的代码,但它会重新创建您已经习惯的行为。请注意,当您实际需要侦听器的另一个类,并且正在努力找出为什么不调用它时,它不会影响您。

您确定使用2.5调用侦听器吗.3?我向您的测试类添加了一个方法,但无法调用拦截器。因此,实际上,这并不能在所有情况下都起作用,特别是对于任何通用实现,PRoxyGenerator barfs。可能有一种方法可以解决这一问题,但这是一个兔子洞。我警告您,这是一个糟糕的代码。:-)这只是一个想法,你可以采取的方法,但你必须考虑所有的细节和影响,这将有。例如,您可能有一个类在实例化时有副作用,您不希望这些副作用发生在这里。
public class Facility : AbstractFacility
{
    protected override void Init() { Kernel.ComponentRegistered += KernelComponentRegistered; }

    static readonly List<Type> TypesNotToIntercept = new List<Type>
    {
        typeof(IInterceptor),   //Don't intercept Interceptors
        typeof(MulticastDelegate),  //Func<> and the like
        typeof(LateBoundComponent), //Resolved with a factory, such as MongoDatabase
    };

    static void KernelComponentRegistered(string key, IHandler handler)
    {
        if (TypesNotToIntercept.Any(type => type.IsAssignableFrom(implementation));
            return;
        handler.ComponentModel.Interceptors.AddIfNotInCollection(InterceptorReference.ForKey("SomeInterceptor"));
    }
}
try
{
    ProxyGenerator generator = new ProxyGenerator();
    generator.CreateClassProxy(handler.ComponentModel.Implementation);
    handler.ComponentModel.Interceptors.AddIfNotInCollection(InterceptorReference.ForType<MyInterceptor>());
}
catch {}