在Windsor的UsingFactoryMethod中处理异常的正确方法是什么? [英] What is the right way to deal with exceptions in Castle Windsor's UsingFactoryMethod?

查看:240
本文介绍了在Windsor的UsingFactoryMethod中处理异常的正确方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Windor的教程中的Nhibernate持久化工具:

  Kernel.Register(
Component.For< ; ISessionFactory>()
.UsingFactoryMethod(config.BuildSessionFactory)
.LifeStyle.Singleton,
Component.For< ISession>()
.UsingFactoryMethod(k => k。解决< ISessionFactory>()。OpenSession())
.LifeStyle.PerWebRequest);

有时我调用config.BuildSessionFactory将失败(也许我的映射是错误的,或者我的连接字符串是无效或无效)。在调试器中,我可以看到Nhibernate异常被抛出。现在Windsor不能再解决我的 ISession ,因为工厂本身无法实例化。



问题是它似乎没有抱怨。没有调试器,这个异常被静默地丢弃,我应用程序中唯一的症状是我所有的 ISession 依赖关系突然 null 。在 UsingFactoryMethod 中处理异常的正确方法是什么?有一些方法可以让Windsor将这个例外提升到我的应用程序吗?

解决方案

唯一为什么我可以看到城堡吃例外是如果会话被注入为一个属性,这使得Castle认为它是可选的。



这是我如何修复它...我创建了一个激活器,无法设置属性值的异常:

  public class StrictComponentActivator:DefaultComponentActivator 
{
public StrictComponentActivator (ComponentModel模型,IKernelInternal内核,
ComponentInstanceDelegate onCreation,
ComponentInstanceDelegate onDestruction)
:base(model,kernel,onCreation,onDestruction){}

protected override void SetUpProperties (对象实例,CreationContext上下文)
{
instance = ProxyUtil.GetUnproxiedInstance(instance);
var resolver = Kernel.Resolver;
foreach(Model.Properties中的var属性)
{
var value = ObtainPropertyValue(context,property,resolver);

if(value!= null)
{
var setMethod = property.Property.GetSetMethod();
try
{
setMethod.Invoke(instance,new [] {value});
}
catch(Exception ex)
{
throw new ComponentActivatorException(
string.Format(
错误设置属性{1}。{0} +
在组件{2}中。+
请参阅内部异常以获取更多信息。+
如果您不希望Windsor设置此属性+
你可以用+
DoNotWireAttribute或通过注册API进行装饰。,
property.Property.Name,
instance.GetType()。Name,
Model.Name),
ex,Model);
}
}
}
}

私有对象ObtainPropertyValue(CreationContext上下文,PropertySet属性,IDependencyResolver解析器)
{
if(property.Dependency.IsOptional == false ||
resolver.CanResolve(context,context.Handler,Model,property.Dependency))
{
try
{
return resolver.Resolve(context,context.Handler,Model,property.Dependency);
}
catch(异常e)
{
if(property.Dependency.IsOptional == false)
{
throw;
}
Kernel.Logger.Warn(
string.Format(在组件{1}上解析可选依赖关系{0}时的异常,
property.Dependency,Model。名称),e);
}
}
返回null;
}
}

然后我用code> .Activator< StrictComponentActivator>()


I'm using the Nhibernate persistence facility from Windor's tutorial:

Kernel.Register(
    Component.For<ISessionFactory>()
        .UsingFactoryMethod(config.BuildSessionFactory)
        .LifeStyle.Singleton,
    Component.For<ISession>()
        .UsingFactoryMethod(k => k.Resolve<ISessionFactory>().OpenSession())
        .LifeStyle.PerWebRequest);

Sometimes my call to config.BuildSessionFactory will fail (maybe my mappings are wrong, or my connection string is invalid or whatever). In the debugger, I can see the Nhibernate exception being thrown. Now Windsor can no longer resolve my ISession either because the factory itself couldn't be instantiated.

The problem is that it doesn't seem to complain about it. Without the debugger, the exception is silently thrown away and the only symptom I have in my app is that all my ISession dependencies are suddenly null. What's the right way to deal with exceptions in UsingFactoryMethod? Is there some way I can tell Windsor to bubble up this exception to my app?

解决方案

The only why I can see Castle eating the exception is if the session is being injected as a property, which makes Castle consider it optional.

Here's how I fixed it... I created an activator that throws an exception when it fails to set a property's value:

public class StrictComponentActivator : DefaultComponentActivator
{
    public StrictComponentActivator(ComponentModel model, IKernelInternal kernel,
        ComponentInstanceDelegate onCreation,
        ComponentInstanceDelegate onDestruction)
        : base(model, kernel, onCreation, onDestruction) { }

    protected override void SetUpProperties(object instance, CreationContext context)
    {
        instance = ProxyUtil.GetUnproxiedInstance(instance);
        var resolver = Kernel.Resolver;
        foreach(var property in Model.Properties)
        {
            var value = ObtainPropertyValue(context, property, resolver);

            if(value != null)
            {
                var setMethod = property.Property.GetSetMethod();
                try
                {
                    setMethod.Invoke(instance, new[] { value });
                }
                catch(Exception ex)
                {
                    throw new ComponentActivatorException(
                        string.Format(
                            "Error setting property {1}.{0} " +
                            "in component {2}. " +
                            "See inner exception for more information. " +
                            "If you don't want Windsor to set this property " +
                            "you can do it by either decorating it with " +
                            "DoNotWireAttribute or via registration API.",
                            property.Property.Name,
                            instance.GetType().Name,
                            Model.Name),
                        ex, Model);
                }
            }
        }
    }

    private object ObtainPropertyValue(CreationContext context, PropertySet property, IDependencyResolver resolver)
    {
        if(property.Dependency.IsOptional == false ||
            resolver.CanResolve(context, context.Handler, Model, property.Dependency))
        {
            try
            {
                return resolver.Resolve(context, context.Handler, Model, property.Dependency);
            }
            catch(Exception e)
            {
                if(property.Dependency.IsOptional == false)
                {
                    throw;
                }
                Kernel.Logger.Warn(
                    string.Format("Exception when resolving optional dependency {0} on component {1}.",
                        property.Dependency, Model.Name), e);
            }
        }
        return null;
    }
}

And then I configured most of my components with .Activator<StrictComponentActivator>()

这篇关于在Windsor的UsingFactoryMethod中处理异常的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆