0

假设我有一个名为 FooController 的类,其中我有一个名为 Bar 的 IBar 类型(接口)的属性。我需要通过 MEF 初始化 Bar。但是,我需要 MEF 在应用程序期间只创建一个 IBar 类型的实例(尽管由于多个请求而多次调用来初始化它)并使其同时可用于所有请求。请注意,可以假定 IBar 实现是线程安全的。

IE

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 实例,尽管有多个请求。

提前致谢。

4

2 回答 2

1

您需要在导出中指定PartCreationPolicy属性。MyBar像这样:

[Export(typeof(IBar))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class MyBar : IBar
{
    // ...
}

这也意味着您不需要在导入时指定创建策略:

[Import]
public IBar Bar { get; set; }
于 2013-01-27T21:13:45.350 回答
0

MEF 的 ASP.NET MVC 集成将每个 HTTP 请求解释为单个实例CreationPolicy.AnyCreationPolicy.Shared您需要将该ApplicationShared属性应用于部件以在 HTTP 请求之间共享它。

更新:

ApplicationSharedAttribute可以在程序集中找到System.ComponentModel.Composition.Web.Mvc。不幸的是,这并没有随 Framework 4.5 一起发布。可以在lib文件夹中的Using MEF with ASP.NET MVC 3 示例代码示例中找到它。缺点是您必须参考找到它的组合程序集,而不是最新的样本。

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

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

还有很多其他更复杂的方法,但这应该可以帮助您入门。

于 2013-01-31T23:40:04.407 回答