2017-04-02 100 views
0

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

也许一个例子会更好。

我有两个类:

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.

我不得不改变MySingletonInstancePerDependency所以它会工作,这对我来说是一个坏的解决方案,因为MySingleton可以创建昂贵。

我在这里错过了什么?

+0

这是正常的行为。您使用“MyScope”的InstancePerMatchingLifetimeScope和“root”注册“MyScoped”。 * Autofac *将首先查找第一个匹配的生命周期“MyScope”,然后查看该范围内是否有任何“MyScoped”实例。如果不是,它会创建一个新的。如果您在“InstancePerMatchingLifetimeScope”声明中删除“MyScope”,它将按预期工作。你能向我们解释你想做什么吗? –

回答

0

看起来作为单个实例注册的服务在根作用域的上下文中解决。这意味着您注入MySingletonFunc<MyScoped>将始终从根目录解析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(); 
} 

将打印1次,因为在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); 
} 

这将分别打印110

+0

不幸的是,这不是一个好的解决方案IMO。这将需要我依赖于整个堆栈的依赖关系。 – Elad