我试图解决IoC问题,起初看起来很容易,但事实证明这是一个痛苦的问题:-P
我有一个重量级的主类,必须只初始化一次,所以它被标记为Singleton。但是这个类使用的子类必须为每个请求创建一次,因此它被标记为Transient:
public class MyRegistry : Registry
{
public MyRegistry()
{
For<IMainClass>()
.Singleton()
.Use(ctx => new MainClass(() => ctx.GetInstance<ISubClass>()));
For<ISubClass>()
.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<ISubClass> _subClassProvider;
public MainClass(Func<ISubClass> subClassProvider)
{
_subClassProvider = subClassProvider;
}
public void DoStuff()
{
var requestSpecificInstanceOfSubClass = _subClassProvider();
// ...
}
}
如您所见,我将lambda传递给MainClass
的构造函数,该构造函数用于获取ISubClass
的实例。在调试期间,我确实可以看到每次ctx.GetInstance<ISubClass>()
需要MainClass
实例时都会执行SubClass
。但令我惊讶的是,SubClass
仅作为单身创建一次,而不是为每个请求创建。
但是,当我直接从代码中的某个地方调用container.GetInstance<ISubClass>()
时,行为完全符合要求。 SubClass
为每个请求创建一次且仅创建一次。
我不太确定,但我猜问题来自传递给lambda的上下文对象,它是单例(?)的上下文。但我真的不知道如何在这里得到理想的行为!?
我希望你能帮助我解决这个问题。谢谢你的回答。
此致 但丁
答案 0 :(得分:0)
这很正常。
因为您正在解决Mainton中的ISubclass,它是单例。
当Main Class解决时,它将获得一个Subclass并且它们将共存(它们必须因为main是singlenton)。
当你解决时,你应该检查第一个父生命周期,如果它是单身,你对每个请求或每个依赖关系无关紧要,它将与单身生活在一起。
答案 1 :(得分:0)
您似乎需要重新设计一下设计。为了避免使用captive dependencies,您需要为图的根对象提供比其任何依赖项更短(或相等)的生命周期。
一种选择是建立第3课来管理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<IInteractionManager>()
.Transient()
.Use<InteractionManager>();
// ...therefore, it can have transient dependencies...
For<ISubClass>()
.Transient()
.Use<SubClass>();
// ...and singleton dependencies.
For<IMainClass>()
.Singleton()
.Use<MainClass>();
}
}
答案 2 :(得分:0)
如果您确实需要 #lineForUrl a #title-font{
word-wrap: break-word;
}
@media screen and (max-width: 480px) {
#footer {
padding: 2em 1em 0.1em 1em;
}
#lineForUrl a #title-font {
max-width: 100%;
overflow: visible;
display: inline-block;
font-size: smaller;
}
}
成为长期存在的对象,但每个请求使用一个新的MainClass
对象,您可以:
1。)将Func的自定义实例注册到容器或MainClass本身的注册,该注册委托给根 Container 本身。请记住,您也可以使用自动布线,因此您不必全部内联。
2.。)将IContainer本身注入MainClass并将其用作服务定位器,以便在每次请求期间懒惰地检索新的ISubClass。
使用IContext的方式不起作用,因为IContext与原始请求相关联。 StructureMap中的“瞬态”实际上意味着“每个请求”,因此当您将Func注入到委托给原始IContext的单例中时,每次都会获得完全相同的ISubClass。有关生命周期的详细信息,请参阅http://structuremap.github.io/object-lifecycle/。
我是SM的作者btw。