使用InstancePerMatchingLifetimeScope的Autofac Func <t>

时间:2017-04-02 16:42:41

标签: .net dependency-injection autofac

在评估Func<T> T注册InstancePerMatchingLifetimeScope时,在单例类中,它不应该提供相同的实例吗?也就是说,Func<T>不应该是“范围感知”?

也许一个例子会更好。

我有两节课:

    class MyScoped
    {
        public int Num { get; set; }
    }

    class MySingleton
    {
        readonly Func<MyScoped> scoped;

        public MySingleton(Func<MyScoped> scoped)
        {
            this.scoped = scoped;
        }

        public void Do()
        {
            var scopedObj = scoped();

            Console.WriteLine(scopedObj.Num);
        }
    }

注册如下:

        var builder = new ContainerBuilder();

        builder.RegisterType<MyScoped>().InstancePerMatchingLifetimeScope("MyScope", "root");
        builder.RegisterType<MySingleton>().SingleInstance();

        var container = builder.Build();

我正在运行以下代码:

        var singleton = container.Resolve<MySingleton>();

        singleton.Do();

        using (var scope = container.BeginLifetimeScope("MyScope"))
        {
            var scoped = scope.Resolve<MyScoped>();

            scoped.Num = 1;

            singleton.Do();
        }

我希望第一次拨打Do()会打印0,第二次拨打会打印1。

我必须将MySingleton更改为InstancePerDependency以便它可以正常工作,这对我来说是一个糟糕的解决方案,因为创建MySingleton代价很高。

我在这里缺少什么?

1 个答案:

答案 0 :(得分:0)

似乎在根范围的上下文中解析了注册为单个实例的服务。这意味着注入Func<MyScoped>的{​​{1}}将始终从根目录解析MySingleton。以下代码:

MyScoped

将打印两次,因为var singleton = container.Resolve<MySingleton>(); var s = container.Resolve<MyScoped>(); s.Num = 1; singleton.Do(); using (var scope = container.BeginLifetimeScope("MyScope")) { var scoped = scope.Resolve<MyScoped>(); scoped.Num = 10; singleton.Do(); } 方法中的var scopedObj = scoped();将从根容器解析Do(),而不是从范围解析。

您可以通过手动将所需的依赖项传递到MyScoped方法来实现您的目标:

Do()

它将分别打印class MySingleton { public void Do(MyScoped myScoped) { Console.WriteLine(myScoped.Num); } } // ... var singleton = container.Resolve<MySingleton>(); var s = container.Resolve<MyScoped>(); s.Num = 1; singleton.Do(s); using (var scope = container.BeginLifetimeScope("MyScope")) { var scoped = scope.Resolve<MyScoped>(); scoped.Num = 10; singleton.Do(scoped); } 1