如何根据Autofac中的可选参数将类注册为singleton
本文关键字:参数 注册 singleton 何根 Autofac | 更新日期: 2023-09-27 17:59:36
让我用代码解释我的问题,这样我就有了一个类:
public class ComplexEntity
{
private readonly ISomeDependency _someDependency;
private readonly int _optionalArg;
public ComplexEntity(ISomeDependency someDependency, int optionalArg)
{
_someDependency = someDependency;
_optionalArg = optionalArg;
}
}
和模块:
public class FooModule : Module
{
protected override void OnMap(ContainerBuilder builder)
{
builder.RegisterType<ConcreteDependency>().As<ISomeDependency>().SingleInstance();
builder.RegisterType<ComplexEntity>().AsSelf();//SingleInstance fails my test below.
}
}
所以我的问题是-我如何使用可选参数(类型为int-实际上,什么类型无关紧要)来解析ComplexEntity
,并且根据该可选参数,它将返回相同的实体(如果已经被请求)或创建一个新实体-只需查看以下测试:
int optionalArgument = 10;
int anotherOptionalArgument = 11;
//I expect ResolveOptional returns same references for the same optional argument,
//thus instance1 should be equals instance2, but not equals instance3
var instance1 = _container.ResolveOptional<ComplexEntity>(
new TypedParameter(optionalArgument.GetType(), optionalArgument));
var instance2 = _container.ResolveOptional<ComplexEntity>(
new TypedParameter(optionalArgument.GetType(), optionalArgument));
var instance3 = _container.ResolveOptional<ComplexEntity>(
new TypedParameter(anotherOptionalArgument.GetType(), anotherOptionalArgument));
bool ref12Equals = object.ReferenceEquals(instance1, instance2); //should be true
bool ref13Equals = object.ReferenceEquals(instance1, instance3); //should be false
bool ref23Equals = object.ReferenceEquals(instance2, instance3); //should be false
在autofac中,作用域可以是singleton或factory(transient),而不是两者都有。如果你需要更复杂的终身管理,我相信你需要对此负责,并自己管理。如果我完全理解您的话,那么您需要一个范围管理器来生成新实例或返回singleton。如果你仍然想使用DI,你可以把它放在容器里,就像这样:
private const int FactoryMode = 11;
private const int SingletonMode = 10;
public static void Main()
{
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<ComplexTypeScope>().SingleInstance();
containerBuilder.Register((c, p) => c.Resolve<ComplexTypeScope>().Get(p.TypedAs<int>()));
var container = containerBuilder.Build();
ComplexType instance1 = container.Resolve<ComplexType>(new TypedParameter(typeof(int), SingletonMode));
ComplexType instance2 = container.Resolve<ComplexType>(new TypedParameter(typeof(int), SingletonMode));
ComplexType instance3 = container.Resolve<ComplexType>(new TypedParameter(typeof(int), FactoryMode));
Debug.Assert(ReferenceEquals(instance1, instance2));
Debug.Assert(!ReferenceEquals(instance1, instance3));
}
class ComplexType
{
}
class ComplexTypeScope
{
private readonly Lazy<ComplexType> complexTypeSingleTon;
public ComplexTypeScope()
{
complexTypeSingleTon = new Lazy<ComplexType>(() => new ComplexType());
}
public ComplexType Get(int parameter)
{
return parameter == FactoryMode ? new ComplexType() : complexTypeSingleTon.Value;
}
}
当然,使用这种方法,容器不会像自动处理一样管理组件的寿命。