【发布时间】:2011-10-24 22:01:42
【问题描述】:
我在 asp.net 中使用 Autofac 2.5,我遇到了一个问题,即生命周期范围的组件被解析为单实例组件的依赖关系,从而破坏了我的线程安全。这是注册的问题,但我认为 Autofac 认为这是违规行为并会引发异常。
private class A{}
private class B
{
public B(A a){}
}
[Test]
[ExpectedException()]
public void SingleInstanceCannotResolveLifetimeDependency()
{
var builder = new ContainerBuilder();
builder.RegisterType<A>()
.InstancePerLifetimeScope();
builder.RegisterType<B>()
.SingleInstance();
using (var container = builder.Build())
{
using (var lifetime = container.BeginLifetimeScope())
{
//should throw an exception
//because B is scoped singleton but A is only scoped for the lifetime
var b = lifetime.Resolve<B>();
}
}
}
如果发生这种情况,有没有办法让 Autofac 抛出依赖解析异常?
更新 即使这是 Autofac 的正确行为 - SingleInstance 只是 Root 生命周期范围内的 - 它在 Web 环境中可能存在潜在危险。确保所有开发人员都获得正确的注册可能会很痛苦。这是 Autofac 的一个小型扩展方法,它检查实例查找以确保生命周期范围内的实例不会在根范围内得到解析。我知道它帮助我们从 Web 项目中清除了生命周期问题。
public static class NoLifetimeResolutionAtRootScopeExtensions
{
/// <summary>
/// Prevents instances that are lifetime registration from being resolved in the root scope
/// </summary>
public static void NoLifetimeResolutionAtRootScope(this IContainer container)
{
LifetimeScopeBeginning(null, new LifetimeScopeBeginningEventArgs(container));
}
private static void LifetimeScopeBeginning(object sender, LifetimeScopeBeginningEventArgs e)
{
e.LifetimeScope.ResolveOperationBeginning += ResolveOperationBeginning;
e.LifetimeScope.ChildLifetimeScopeBeginning += LifetimeScopeBeginning;
}
private static void ResolveOperationBeginning(object sender, ResolveOperationBeginningEventArgs e)
{
e.ResolveOperation.InstanceLookupBeginning += InstanceLookupBeginning;
}
private static void InstanceLookupBeginning(object sender, InstanceLookupBeginningEventArgs e)
{
var registration = e.InstanceLookup.ComponentRegistration;
var activationScope = e.InstanceLookup.ActivationScope;
if (registration.Ownership != InstanceOwnership.ExternallyOwned
&& registration.Sharing == InstanceSharing.Shared
&& !(registration.Lifetime is RootScopeLifetime)
&& activationScope.Tag.Equals("root"))
{
//would be really nice to be able to get a resolution stack here
throw new DependencyResolutionException(string.Format(
"Cannot resolve a lifetime instance of {0} at the root scope.", registration.Target))
}
}
}
只需在创建容器时应用它,当生命周期范围内的服务在根范围内解析时,您将得到抛出异常。
container.NoLifetimeResolutionAtRootScope();
【问题讨论】:
标签: .net dependency-injection autofac