在一个部件组合中,导入将触发一个部件或者多个部件的实例化,这些部件暴露了所需原请求部件的必要的导入。对于一些应用程序来说,延迟实例化-防止图结构下的递归组合-可能对于将创建一个长久复杂的开销很大而不必要的对象的图来说是一个重要的因素。
正是出于这样的动机,MEF支持叫做lazy exports的导出。为了使用它,你需要做的是直接导入一个[System.Lazy<T>]而不是的[T]。例如,考虑下面的代码片段:
public class HttpServerHealthMonitor { [Import] public IMessageSender Sender { get; set; } }
上面导入的代码声明了一个依赖契约(IMessageSender)实现。当MEF提供这种依赖的时候,它也将需要创建选中的IMessageSender和递归地创建这些实现可能有的依赖。
为了使导入变的延迟,你仅仅需要用Lazy<IMessageSender>来替换它:
[Export] public class HttpServerHealthMonitor { [Import] public Lazy<IMessageSender> Sender { get; set; } }
在这种情况下,你是选择在拖延这个实例化,直到你真正需要这些实现实例。为了请求实例,请使用[Lazy<T>.Value]属性。
举个例子:
using System; using System.Collections.Generic; using System.ComponentModel.Composition; using System.ComponentModel.Composition.Hosting; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace ImportsDeclaring { class Example2 { [Import] private Lazy<ILogger> logger; static void Main() { Example2 e2 = new Example2(); e2.Compose(); e2.logger.Value.Log("Hi,MEF");//获取Lazy<T>.Value才真正实例化Logger Console.ReadKey(); } void Compose() { var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly()); var container = new CompositionContainer(catalog); container.ComposeParts(this); } } interface ILogger { void Log(string msg); } [Export(typeof(ILogger))] class Logger : ILogger { public Logger() { } public void Log(string msg) { Console.WriteLine("Logging..."); } } }
输出结果:
Lazy<T>是.net 4.0的特性,实质还是对象的创建问题,在某些场合,对于一些实例化开销很大的对象使用。其Value属性才是真实T对象,当第一次访问Value属性时就会自动创建T实例。除了调用默认的构造器外,还可以调用重载的构造器来实例T。另外,也提供了多线程的支持。