2

WindorのチュートリアルのNhibernate永続化機能を使用しています。

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

config.BuildSessionFactoryの呼び出しが失敗することがあります(マッピングが間違っているか、接続文字列が無効であるなど)。デバッガーで、Nhibernate例外がスローされているのを確認できます。ISession工場自体をインスタンス化できなかったため、Windsorは私のどちらも解決できなくなりました。

問題は、それについて文句を言っていないように見えることです。デバッガーがないと、例外は黙って破棄され、アプリで発生する唯一の症状は、すべてのISession依存関係が突然発生することnullです。の例外に対処する正しい方法は何UsingFactoryMethodですか?この例外をアプリにバブルアップするようにWindsorに指示する方法はありますか?

4

1 に答える 1

1

キャッスルが例外を食べているのを見ることができる唯一の理由は、セッションがプロパティとして注入されている場合です。これにより、キャッスルはそれをオプションと見なします。

これを修正した方法は次のとおりです...プロパティの値の設定に失敗したときに例外をスローするアクティベーターを作成しました。

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;
    }
}

そして、ほとんどのコンポーネントを次のように構成しました.Activator<StrictComponentActivator>()

于 2012-08-17T14:18:04.850 に答える