问题
I'd like to have an instance per matching lifetime scoped registration in Autofac, but occasionally need to request an instance from a global container (where there is no matching lifetime scope). In scenarios where no matching lifetime scope exists, I want to give a top-level instance instead of throwing an exception.
Is this possible?
回答1:
I think you'd better extend Autofac by introducing a new lifetime option. I took the Autofac sources and modified them a bit:
public static class RegistrationBuilderExtensions
{
public static IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> InstancePerMatchingOrRootLifetimeScope<TLimit, TActivatorData, TRegistrationStyle>(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;
}
}
Just add these classes to your project and register you component as:
builder.RegisterType<A>.InstancePerMatchingOrRootLifetimeScope("TAG");
I haven't tried it myself, but it should work.
回答2:
Possible solution is to override registration in child lifetime scope.
Sample:
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();
}
}
来源:https://stackoverflow.com/questions/14672541/instance-per-matching-lifetime-scope-with-default