StructureMap:创建为瞬态(每个请求)不起作用
我正试图解决一个IoC问题,起初看起来很容易,但结果却是一个痛苦的屁股:-P
我有一个重量级的主类,必须初始化一次,所以它被标记为Singleton。 但是,这个类使用的子类必须为每个请求创建一次,因此它被标记为Transient:
public class MyRegistry : Registry { public MyRegistry() { For() .Singleton() .Use(ctx => new MainClass(() => ctx.GetInstance())); For() .Transient() .Use(ctx => CreateNewInstanceOfSubClass()); } private ISubClass CreateNewInstanceOfSubClass() { return new SubClass(); } } public interface ISubClass { } public class SubClass : ISubClass { } public interface IMainClass { } public class MainClass : IMainClass { private readonly Func _subClassProvider; public MainClass(Func subClassProvider) { _subClassProvider = subClassProvider; } public void DoStuff() { var requestSpecificInstanceOfSubClass = _subClassProvider(); // ... } }
如您所见,我将lambda传递给MainClass
的构造函数,该构造函数用于获取ISubClass
的实例。 在调试期间,我肯定会看到每次MainClass
需要SubClass
实例时MainClass
执行ctx.GetInstance()
。 但令我惊讶的是, SubClass
只创建一次作为单例,而不是为每个请求创建。
但是,当我直接从我的代码中的某个地方调用container.GetInstance()
,行为完全符合要求。 SubClass
为每个请求创建一次且仅创建一次。
我不太确定,但我猜这个问题来自传递给lambda的上下文对象,它是单例(?)的上下文。 但我真的不知道如何在这里得到理想的行为!?
我希望你能帮我这个。 谢谢你的回答。
此致,但丁
看来你需要重新设计一下。 为了避免使用强制依赖 ,您需要为图的根对象提供比其任何依赖项更短(或相等)的生命周期。
一种选择是创建第三类来管理MainClass
和SubClass
之间的交互。
接口
public interface IInteractionManager { void DoStuff(); } public interface IMainClass { void DoStuff(ISubclass subclass); } public interface ISubClass { }
类
public class InteractionManager : IInteractionManager { private readonly IMainClass mainClass; private readonly ISubClass subClass; public InteractionManager( IMainClass mainClass, ISubClass subClass) { this.mainClass = mainClass; this.subClass = subClass; } public void DoStuff() { this.mainClass.DoStuff(this.subClass); } } public class MainClass : IMainClass { public void DoStuff(ISubclass subclass) { // do something with transient subclass } } public class SubClass : ISubClass { }
注册处
public class MyRegistry : Registry { public MyRegistry() { // The root of the object graph is transient... For() .Transient() .Use(); // ...therefore, it can have transient dependencies... For() .Transient() .Use(); // ...and singleton dependencies. For() .Singleton() .Use(); } }
这很正常。
因为你在Main类中解析ISubclass是单例。
当Main Class解决时,它将获得一个Subclass并且它们将一起生活(它们必须因为main是singlenton)。
当你解决时,你应该检查第一个父生命周期,如果它是单身,你有每个请求或每个依赖关系无关紧要,它将与单身一起生活。
如果您确实需要MainClass
成为长期存在的对象,但每个请求使用一个新的SubClass
对象,您可以:
1.)将一个自定义Func实例注册到容器,或注册到MainClass本身,该代理将委托给根容器本身。 请记住,您也可以使用自动布线,因此您不必全部内联。
2.)将IContainer本身注入MainClass,并将其用作服务定位器,在每次请求期间懒惰地检索新的ISubClass。
使用IContext将无法正常工作,因为IContext与原始请求相关联。 StructureMap中的“瞬态”实际上意味着“按请求”,因此当您将Func注入到委托给原始IContext的单例中时,每次都会得到完全相同的ISubClass。 有关生命周期的更多信息,请参见http://structuremap.github.io/object-lifecycle/ 。
我是SM的作者btw。