参数化实例化如何与 SingleInstance lifescope 配合使用

Bil*_*ang 2 c# autofac

Parameterized Instantiation( Func<X, Y, B>)文档中,最后一句话说

但是,如果您将一个对象注册为 SingleInstance() 并多次调用 Func 来解析该对象,则无论您传入的参数不同,每次都会获得相同的对象实例。 仅传递不同的参数不会破坏尊重对于生命周期范围。

它如何工作具有不同参数构造函数的单例类。

Cyr*_*and 6

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)

foo1foo2将不同而foo1Prime将与foo1.