在Parameterized Instantiation( Func<X, Y, B>)文档中,最后一句话说
但是,如果您将一个对象注册为 SingleInstance() 并多次调用 Func 来解析该对象,则无论您传入的参数不同,每次都会获得相同的对象实例。 仅传递不同的参数不会破坏尊重对于生命周期范围。
它如何工作具有不同参数构造函数的单例类。
Autofac工厂注册不会缓存每个参数的实例。
让我们试一试,想象一下以下类型:
public class Foo
{
public Foo(Int32 a)
{
this._a = a;
}
private readonly Int32 _a;
public override String ToString()
{
return String.Format("a={0}", this._a);
}
}
Run Code Online (Sandbox Code Playgroud)
如果你这样注册:
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<Foo>().AsSelf().SingleInstance();
Run Code Online (Sandbox Code Playgroud)
Autofac将始终注册一个。无论您如何解决它(如果您使用 func 工厂,则为事件)。
Func<Int32, Foo> foo1Factory = scope.Resolve<Func<Int32, Foo>>();
Foo foo1 = foo1Factory(1);
Func<Int32, Foo> foo2Factory = scope.Resolve<Func<Int32, Foo>>();
Foo foo2 = foo2Factory(2);
Run Code Online (Sandbox Code Playgroud)
foo1并且foo2将是同一个实例。
如果您希望每个参数只有 1 个实例,则意味着您需要多个 的实例Foo,因此您无法注册FoousingSingleInstance()方法。您将必须实现一个自定义工厂,该工厂将缓存每个参数有 1 个实例。
public class FooFactory
{
public FooFactory(IComponentContext componentContext)
{
this._componentContext = componentContext;
this._instances = new Dictionary<Int32, Foo>();
this._lock = new Object();
}
private readonly IComponentContext _componentContext;
private readonly Dictionary<Int32, Foo> _instances;
private readonly Object _lock;
public Foo GetInstance(Int32 a)
{
Foo parameterizedFoo;
if (!this._instances.TryGetValue(a, out parameterizedFoo))
{
lock (this._lock)
{
if (!this._instances.TryGetValue(a, out parameterizedFoo))
{
Parameter aParameter = new TypedParameter(typeof(Int32), a);
parameterizedFoo = this._componentContext
.Resolve<Foo>(aParameter);
this._instances[a] = parameterizedFoo;
}
}
}
return parameterizedFoo;
}
}
Run Code Online (Sandbox Code Playgroud)
你可以这样注册:
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<Foo>().AsSelf();
builder.RegisterType<FooFactory>().AsSelf().SingleInstance();
Run Code Online (Sandbox Code Playgroud)
使用以下代码来使用它:
FooFactory fooFactory = scope.Resolve<FooFactory>();
Foo foo = fooFactory.GetInstance(1);
Run Code Online (Sandbox Code Playgroud)
但是,如果您不想使用FooFactory.GetInstance代替Func<Int32, Foo>,则可以将该方法注册为Func<Int32, Foo>
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<Foo>().AsSelf();
builder.RegisterType<FooFactory>().AsSelf().SingleInstance();
builder.Register(c => new Func<Int32, Foo>(c.Resolve<FooFactory>().GetInstance))
.As<Func<Int32, Foo>>()
.SingleInstance();
Run Code Online (Sandbox Code Playgroud)
您现在可以使用此代码
Func<Int32, Foo> foo1Factory = scope.Resolve<Func<Int32, Foo>>();
Foo foo1 = foo1Factory(1);
Func<Int32, Foo> foo2Factory = scope.Resolve<Func<Int32, Foo>>();
Foo foo2 = foo2Factory(2);
Func<Int32, Foo> foo1PrimeFactory = scope.Resolve<Func<Int32, Foo>>();
Foo foo1Prime = foo1PrimeFactory(1);
Run Code Online (Sandbox Code Playgroud)
foo1和foo2将不同而foo1Prime将与foo1.