我们为我们的项目调查DI容器。现在我们选择Autofac和Castle Windsor。对我们来说有一些非常重要的事情:强烈输入Autofac的注册。
示例:
public interface ITestAutofac
{
}
public class NotDerivedFrom
{
}
对于温莎,我可以写这样的东西 -
var cont = new WindsorContainer();
cont.Register(Component
.For<ITestAutofac>().ImplementedBy<NotDerivedFrom>());
编译时会失败。 Resharper可以轻松地帮助解决这个问题。
对于Autofac,我可以这样写 -
builder.Register(c => new NotDerivedFrom()).As<ITestAutofac>();
var form = container.Resolve<ICustomForm>();
它会在运行时失败。
如何通过编译时间检查在Autofac中注册类型?
答案 0 :(得分:4)
builder.Register<NotDerivedFrom>().As<ITestAutofac>()
使用Autofac时,这会在运行时失败,但是当你调用builder.Build()
时会发生这种情况,当你想到这一点时这并不是很糟糕。我同意,它不如编译时支持那么好,但你可以找到一个调用builder.Build()
的单元测试。不要忘记大多数DI配置错误永远不会被编译器捕获,您需要使用容器a verifiable configuration和一些单元测试来查找所有配置错误。
如何通过编译时间检查在Autofac中注册类型?
如果您愿意,可以编写一个简单的扩展方法来添加编译时检查:
public static void Register<TService, TImplementation>(
this ContainerBuilder builder)
// Note the generic type constraints here
where TImplementation: class, TService
where TService: class
{
builder.Register<TImplementation>().As<TService>();
}
这允许您按如下方式进行原始注册:
build.Register<ITestAutofac, NotDerivedFrom>();
在编译时会失败。
答案 1 :(得分:0)
根据Steven的回答,我更新了扩展方法以返回IRegistrationBuilder
以使其能够继续使用注册(设置范围等):
public static class ContainerBuilderExtensions
{
public static IRegistrationBuilder<TImplementation, ConcreteReflectionActivatorData, SingleRegistrationStyle>
RegisterType<TService, TImplementation>(this ContainerBuilder builder)
where TImplementation : class, TService
where TService : class
{
return builder.RegisterType<TImplementation>().As<TService>();
}
}
使用示例:
var builder = new ContainerBuilder();
builder.RegisterType<IMyFactory, MyFactory>().SingleInstance();
var container = builder.Build();