asp.net에서 Autofac 2.5를 사용하고 있으며 수명 인스턴스 구성 요소가 단일 인스턴스 구성 요소의 종속성으로 해결되어 내 스레드 안전을 손상시키는 문제가 있습니다. 이것은 등록 문제이지만 Autofac이이를 위반으로보고 예외를 던질 것으로 생각했습니다.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에서 종속성 해결 예외를 발생시키는 방법이 있습니까? SingleInstance이 범위 단지 루트 수명입니다 - - 그것은 웹 환경에서 잠재적으로 위험 할 수 있습니다이 Autofac에 대한 올바른 동작이 비록
UPDATE . 모든 개발자가 올바른 등록을 받도록하는 것이 고통 스러울 수 있습니다. 다음은 수명 범위 영역 인스턴스가 루트 범위에서 확인되지 않도록 인스턴스 조회를 검사하는 Autofac의 작은 확장 방법입니다. 웹 프로젝트에서 생명주기 문제를 제거하는 데 도움이되었다는 것을 알고 있습니다.
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();
감사합니다, 그것은 하나의 인스턴스가 단지 루트 수명이 범위 것을 알아낼 걸 렸어요. – Danielg
작은 확장 메서드를 사용하여 내 질문을 업데이트하여 이러한 예외를 throw합니다. "_activationStack"이 ResolveOperation에 노출되면 더 유용한 정보를 던질 수 있습니다. – Danielg