我想在Autofac中为每个匹配的生命周期范围注册创建一个实例,但偶尔需要从全局容器(没有匹配的生命周期范围)请求实例。在没有匹配的生命周期范围的情况下,我想提供一个顶级实例而不是抛出异常。
这可能吗?
答案 0 :(得分:9)
我认为您最好通过引入新的生命周期选项来扩展Autofac。我使用了Autofac源并对其进行了一些修改:
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;
}
}
只需将这些类添加到项目中,并将组件注册为:
builder.RegisterType<A>.InstancePerMatchingOrRootLifetimeScope("TAG");
我自己没有尝试过,但它应该有用。
答案 1 :(得分:2)
可能的解决方案是覆盖子生命周期范围内的注册。
样品:
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();
}
}
答案 2 :(得分:0)
根容器本身是一个生命周期范围,标签名称为:root
,定义在LifetimeScope.RootTag
所以你可以这样做:
using Autofac.Core.Lifetime;
builder.RegisterType<Service>().As<IService>()
.InstancePerMatchingLifetimeScope(LifetimeScope.RootTag, "foobar");