나는 Autofac에서 수명이 정하는 범위 지정 등록과 일치하는 인스턴스를 갖고 싶지만 때로는 글로벌 컨테이너 (일치하는 수명 범위가없는 인스턴스)를 요청해야합니다. 일치하는 수명 범위가없는 시나리오에서 예외를 throw하는 대신 최상위 인스턴스를 제공하려고합니다.일치하는 수명 범위 당 인스턴스, 기본값은?
이것이 가능합니까?
나는 Autofac에서 수명이 정하는 범위 지정 등록과 일치하는 인스턴스를 갖고 싶지만 때로는 글로벌 컨테이너 (일치하는 수명 범위가없는 인스턴스)를 요청해야합니다. 일치하는 수명 범위가없는 시나리오에서 예외를 throw하는 대신 최상위 인스턴스를 제공하려고합니다.일치하는 수명 범위 당 인스턴스, 기본값은?
이것이 가능합니까?
난 당신이 더 나은 새로운 평생 옵션을 도입하여 Autofac을 확장 거라고 생각합니다. 나는 Autofac 소스를 가져다가 그들에게 조금 수정 :
public static class RegistrationBuilderExtensions
{
public IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> InstancePerMatchingOrRootLifetimeScope(this IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> builder, params object[] lifetimeScopeTag)
{
if (lifetimeScopeTag == null) throw new ArgumentNullException("lifetimeScopeTag");
builder.RegistrationData.Sharing = InstanceSharing.Shared;
builder.RegistrationData.Lifetime = new MatchingScopeOrRootLifetime(lifetimeScopeTag);
return builder;
}
}
public class MatchingScopeOrRootLifetime: IComponentLifetime
{
readonly object[] _tagsToMatch;
public MatchingScopeOrRootLifetime(params object[] lifetimeScopeTagsToMatch)
{
if (lifetimeScopeTagsToMatch == null) throw new ArgumentNullException("lifetimeScopeTagsToMatch");
_tagsToMatch = lifetimeScopeTagsToMatch;
}
public ISharingLifetimeScope FindScope(ISharingLifetimeScope mostNestedVisibleScope)
{
if (mostNestedVisibleScope == null) throw new ArgumentNullException("mostNestedVisibleScope");
var next = mostNestedVisibleScope;
while (next != null)
{
if (_tagsToMatch.Contains(next.Tag))
return next;
next = next.ParentLifetimeScope;
}
return mostNestedVisibleScope.RootLifetimeScope;
}
}
그냥 프로젝트에이 클래스를 추가하고 등록하면 구성 요소로 : 나 자신을 그것을 시도하지 않은
builder.RegisterType<A>.InstancePerMatchingOrRootLifetimeScope("TAG");
을하지만, 그것을 작동합니다 .
가능한 해결책은 자식 수명 범위에서 등록을 재정의하는 것입니다.
샘플 :
public enum Scopes
{
TestScope
}
public class Test
{
public string Description { get; set; }
}
public class Tester
{
public void DoTest()
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<Test>()
.OnActivating(args => args.Instance.Description = "FromRoot")
.SingleInstance();
var container = builder.Build();
var scope = container.BeginLifetimeScope(Scopes.TestScope, b => b
.RegisterType<Test>()
.InstancePerMatchingLifetimeScope(Scopes.TestScope)
.OnActivating(args => args.Instance.Description = "FromScope"));
var test1 = container.Resolve<Test>();
Console.WriteLine(test1.Description); //writes FromRoot
var test2 = scope.Resolve<Test>();
Console.WriteLine(test2.Description); //writes FromScope
Console.ReadLine();
}
}
코드가 다소 혼란 스럽지만 @Memoizer가 옳습니다.이를 수행하는 유일한 방법은 하위 범위의 등록을 무시하는 것입니다. 불행하게도 질문은 "한 곳에서 평생 스코프 스타일을 원하고 다른 곳에서 다른 스타일을 원합니다"라는 질문을 던졌습니다.이 시나리오는 지원되는 시나리오가 아니므로 이런 상황에 맞는 맞춤 코드가 필요합니다. –
왜 필요합니까? 글로벌 등록을 범위 등록과 다르게하고 싶습니까? 또는 글로벌 스코프 및 태그 범위 모두에 대해 구성을 동일하게 유지하면서 소비자가 한 사례에서 인스턴스 하나를 얻고 다른 인스턴스에서 다른 인스턴스를 얻길 원하십니까? –
@PavelGatilov 후자. 동일한 구성, 태그 범위 당 다른 인스턴스 및 전역 범위에 대한 다른 인스턴스. –