asp.net mvc - 如何告诉 MEF 为每个应用程序的给定类型实例化单个对象



假设我有一个名为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.AnyCreationPolicy.Shared解释为每个 HTTP 请求的单个实例。您需要将 ApplicationShared 属性应用于部件,以便在 HTTP 请求之间共享它。

更新:

ApplicationSharedAttribute可以在System.ComponentModel.Composition.Web.Mvc组件中找到。不幸的是,这没有与框架 4.5 一起分发。可以在 lib 文件夹中将 MEF 与 MVC 3 示例代码结合使用 ASP.NET 示例中找到它。缺点是您必须引用找到它的合成程序集,而不是最新的。

如果您不想这样做,请从以下非常简单的方法开始:

  1. MvcApplication 类中添加一个CompositionContainer作为public属性。
  2. 在构造函数MvcApplication上创建容器并添加一些目录。
  3. 在控制器上从HttpContext获取应用程序并使用CompositionContainerGetExport/GetExportedValue/GetExportedValues方法之一。无需在容器上调用ComposeParts

还有很多其他方法更复杂,但这应该让你开始。

最新更新