假设我有一个名为FooController的类,其中我有一个名为Bar的属性,类型为IBar(接口)。我需要通过 MEF 初始化酒吧。但是,我需要 MEF 在应用程序期间仅创建一个 IBar 类型的实例(尽管由于多个请求而多次调用初始化它),并使其同时可用于所有请求。请注意,IBar 实现可以假定是线程安全的。
即
public interface IBar
{
string Method();
}
[Export(typeof(IBar))]
public class MyBar: IBar
{
public string dateTimeCreated;
public MyBar()
{
System.Threading.Thread.Sleep(1000);
dateTimeCreated = DateTime.Now.ToLongTimeString() + " ";
}
public string Method()
{
return dateTimeCreated;
}
}
public class FooController : ApiController
{
[Import(typeof(IBar), RequiredCreationPolicy = CreationPolicy.Shared)]
public IBar Bar { get; set; }
public FooController()
{
//Assume CompositionContainer.ComposeParts call here
}
public string Get()
{
return Bar.Method();
}
}
问题是每次我在 FooController 上调用 Get() 时,返回的时间值都会发生变化。这意味着 MyBar 对象将针对每个调用重新实例化。我基本上需要它返回相同的值,这意味着尽管有多个请求,我只需要告诉 MEF 在我的应用程序中只创建一个 IBar 实例。
提前谢谢。
在MyBar
导出中指定PartCreationPolicy
属性。喜欢这个:
[Export(typeof(IBar))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class MyBar : IBar
{
// ...
}
这也意味着您无需在导入时指定创建策略:
[Import]
public IBar Bar { get; set; }
MEF 的 ASP.NET MVC 集成将CreationPolicy.Any
和CreationPolicy.Shared
解释为每个 HTTP 请求的单个实例。您需要将 ApplicationShared
属性应用于部件,以便在 HTTP 请求之间共享它。
更新:
ApplicationSharedAttribute
可以在System.ComponentModel.Composition.Web.Mvc
组件中找到。不幸的是,这没有与框架 4.5 一起分发。可以在 lib 文件夹中将 MEF 与 MVC 3 示例代码结合使用 ASP.NET 示例中找到它。缺点是您必须引用找到它的合成程序集,而不是最新的。
如果您不想这样做,请从以下非常简单的方法开始:
- 在
MvcApplication
类中添加一个CompositionContainer
作为public
属性。- 在构造函数
MvcApplication
上创建容器并添加一些目录。 - 在控制器上从HttpContext获取应用程序并使用
CompositionContainer
的GetExport
/GetExportedValue
/GetExportedValues
方法之一。无需在容器上调用ComposeParts
。
还有很多其他方法更复杂,但这应该让你开始。