如果我有以下模块:
class MyModule : Module
{
public double SomeDouble { get; set; }
}
我的app.config
<autofac>
<modules>
<module type="MyNamespace.MyModule, MyNamespace">
<properties>
<property name="SomeDouble" value="" />
</properties>
</module>
</modules>
</autofac>
致电builer.Build()
我得到一个例外说:
输入字符串的格式不正确,值对于a无效 双
这是有道理的。
我希望能够做的是提供某种处理异常的处理程序,而不是让整个Build()
失败,或提供默认值。
此刻可以在autofac中使用吗?
答案 0 :(得分:1)
没有简单的方法可以做到这一点。我能看到的唯一解决方案是向IConfigurationRegistrar
ConfigurationSettingsReader
var builder = new ContainerBuilder();
builder.RegisterModule(new ConfigurationSettingsReader()
{
ConfigurationRegistrar = new CustomConfigurationRegistrar()
});
builder.Build();
CustomConfigurationRegistrar
可以继承默认的ConfigurationRegistrar
。
如果你查看source code,你可以看到RegisterConfiguredModules
将在 foreach 循环中注册所有模块,没有注册单个模块的方法,所以你有从基类复制/过去它。
因为错误来自用于注入属性的参数,我们可以创建一个LazyParameter
来处理错误并返回默认值。
public class CustomConfigurationRegistrar : ConfigurationRegistrar
{
internal class LazyParameter : Parameter
{
public LazyParameter(Parameter originalParameter)
{
this._originalParameter = originalParameter;
}
private readonly Parameter _originalParameter;
public override Boolean CanSupplyValue(ParameterInfo pi, IComponentContext context, out Func<Object> valueProvider)
{
Boolean canSupplyValue = this._originalParameter.CanSupplyValue(pi, context, out valueProvider);
if (canSupplyValue)
{
Func<Object> originalValueProvider = valueProvider;
valueProvider = () =>
{
try
{
return originalValueProvider();
}
catch
{
Console.WriteLine(pi.Member.Name);
// log it and throw or return default value
return null;
}
};
}
return canSupplyValue;
}
}
protected override void RegisterConfiguredModules(ContainerBuilder builder, SectionHandler configurationSection)
{
if (builder == null)
{
throw new ArgumentNullException("builder");
}
if (configurationSection == null)
{
throw new ArgumentNullException("configurationSection");
}
foreach (ModuleElement moduleElement in configurationSection.Modules)
{
this.RegisterConfiguredModule(builder, configurationSection, moduleElement);
}
}
private void RegisterConfiguredModule(ContainerBuilder builder, SectionHandler configurationSection, ModuleElement moduleElement)
{
try
{
var moduleType = this.LoadType(moduleElement.Type, configurationSection.DefaultAssembly);
IModule module = null;
IEnumerable<Parameter> parameters = moduleElement.Parameters.ToParameters().Select(p => new LazyParameter(p));
IEnumerable<Parameter> properties = moduleElement.Properties.ToParameters().Select(p => new LazyParameter(p));
using (var moduleActivator = new ReflectionActivator(
moduleType,
new DefaultConstructorFinder(),
new MostParametersConstructorSelector(),
parameters,
properties))
{
module = (IModule)moduleActivator.ActivateInstance(new ContainerBuilder().Build(), Enumerable.Empty<Parameter>());
}
builder.RegisterModule(module);
}
catch (Exception)
{
// log it
throw;
}
}
}