2012-08-17 65 views
2

我使用從Windor的教程NHibernate的持久性設施:在Castle Windsor的UsingFactoryMethod中處理例外的正確方法是什麼?

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,因爲工廠本身無法實例化。

問題是它似乎沒有抱怨它。如果沒有調試器,這個異常會被無聲地拋棄,我在我的應用程序中唯一的症狀就是我所有的ISession依賴項都是突然的null。在UsingFactoryMethod中處理例外的正確方法是什麼?有什麼辦法可以告訴Windsor泡這個例外給我的應用程序?

+0

我我也在尋找這個......在此期間,我能夠在日誌文件中發現異常情況,以便更好地瞭解Windsor發生了什麼事情:http://stackoverflow.com/a/21007268/114029 – 2014-01-08 22:02:57

回答

1

唯一的原因是我可以看到城堡吃掉異常,如果會話被注入爲一個屬性,這使得Castle認爲它是可選的。

以下是我固定它...我創建拋出失敗時設置一個屬性值的異常活化劑:

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>()

+1

是的,這是被注入的財產。我從來沒有看過自定義激活器,但看起來這是解決它的正確方法。謝謝! – Ragesh 2012-08-17 17:55:22

+0

什麼是ObtainPropertyValue方法? – 2014-08-22 21:32:30

+0

好的...我在這裏找到了https://github.com/castleproject/Windsor/blob/016730de012f15985410fb33e2eb907690fe5a28/src/Castle.Windsor/MicroKernel/ComponentActivator/DefaultComponentActivator.cs#L342。更新了您的答案... – 2014-08-22 21:56:16

相關問題