我正在使用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异常。现在Windsor再也无法解析我的ISession
,因为工厂本身无法实例化。
问题在于它似乎没有抱怨它。如果没有调试器,则会默默地抛弃该异常,并且我的应用程序中唯一的症状是我的所有ISession
依赖项突然null
。在UsingFactoryMethod
处理异常的正确方法是什么?有什么方法可以告诉Windsor将这个异常冒泡到我的应用程序中吗?
答案 0 :(得分:1)
我唯一可以看到Castle吃异常的原因是会话是作为属性注入的,这使得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>()