Structuremap是否支持Lazy开箱即用?

structuremap是否允许您以懒惰的方式进行构造函数注入? 意思是不创建在使用之前注入的对象?

更新: StructureMap v3实现了这个开箱即用的function,因此不再需要这个技巧。


StructureMap版本2没有,但有一些技巧你可以让它做我认为你正在寻找的东西。 首先,您可以手动连接Lazy实例,如下所示:

 container = new Container(x => { x.Scan(y => { y.TheCallingAssembly(); y.WithDefaultConventions(); }); x.For>().Use(y => new Lazy(y.GetInstance)); x.For>().Use(y => new Lazy(y.GetInstance)); x.For>().Use(y => new Lazy(y.GetInstance)); }); 

这很好用,但你必须单独注册每个类型。 如果你能利用更基于惯例的方法,那就更好了。 理想情况下,以下语法会很好。

 x.For(typeof(Lazy<>)).Use(typeof(Lazy<>)); 

这种语法实际上有点…… 不幸的是,在运行时,StructureMap将尝试为Lazy找到“最贪婪”的构造函数并解决public Lazy(Func valueFactory, bool isThreadSafe) 。 由于我们没有告诉它如何处理boolean isThreadSafe参数,因此在尝试解析“Lazy”时会抛出exception。

Lazy的文档声明默认的Lazy(Func valueFactory)构造函数的“线程安全模式”是LazyThreadSafetyMode.ExecutionAndPublication ,这恰好是通过将true传递给上面构造函数的isThreadSafe参数得到的。 因此,如果我们可以告诉StructureMap为isThreadSafe传递true ,那么我们将获得相同的行为,就像我们首先调用我们实际想要使用的构造函数一样(例如Lazy(Func valueFactory) )。

只需注册x.For(typeof(bool)).Use(y => true)将是非常鲁莽和危险的,因为我们将告诉StructureMap继续使用值true任何布尔值的任何地方。 相反,我们需要告诉StructureMap只有这个布尔参数使用什么值,我们可以这样做。

 x.For(typeof(Lazy<>)).Use(typeof(Lazy<>)) .CtorDependency("isThreadSafe").Is(true); 

现在,StructureMap知道在解析Lazy时对isThreadSafe参数使用“true”的值。 我们现在可以在构造函数参数中使用Lazy ,并获得我认为您正在寻找的行为。

您可以在此处详细了解Lazy类。

是的,它确实。 最新版本的StructureMap(2.6.x)是针对.NET Framework 3.5编译的,因此无法访问.NET 4中引入的Lazy类型。但是,它确实支持相同的function – “不创建在使用之前注入的物体“。 您不依赖于Lazy ,而是依赖于Func 。 无需特殊的集装箱登记。

我已经包含了一个创建以下输出的示例程序:

 Created Consumer Consuming Created Helper Helping 

Sample.cs:

 class Program { static void Main(string[] args) { var container = new Container(x => { x.For().Use(); x.For().Use(); }); var consumer = container.GetInstance(); consumer.Consume(); } } public class Consumer : IConsumer { private readonly Func _helper; public Consumer(Func helper) { _helper = helper; Console.WriteLine("Created Consumer"); } public void Consume() { Console.WriteLine("Consuming"); _helper().Help(); } } public interface IConsumer { void Consume(); } public interface IHelper { void Help(); } public class Helper : IHelper { public Helper() { Console.WriteLine("Created Helper"); } public void Help() { Console.WriteLine("Helping"); } }