C#MEF:线程安全导出

C#MEF:线程安全导出,c#,mef,C#,Mef,假设我有一个CarSystem类,其中包含CarParts对象的集合。现在我想给系统写一个立体声插件,我希望所有插件的格式都是: public interface ICarPluginMetaData { string Name {get;} string Description {get;} int Status {get; set;} } public interface ICarPlugin { void int setStatus(int newStatus); }

假设我有一个
CarSystem
类,其中包含
CarParts
对象的集合。现在我想给系统写一个立体声插件,我希望所有插件的格式都是:

public interface ICarPluginMetaData
{
  string Name {get;}
  string Description {get;}
  int Status {get; set;}
}

public interface ICarPlugin
{
  void int setStatus(int newStatus);
}

[Export(typeof(ICarPlugin))]
[ExportMetaData("Name", "Stereo")]
[ExportMetaData("Description","Plays music")]
[ExportMetaData("Status", 0)]
public class StereoPlugin : ICarPlugin
{
  [ICarPluginImport("FrontSpeakers")]
  public CarPart myFrontSpeakersPointer;

  [ICarPluginImport("RearSpeakers")]
  public CarPart myRearSpeakersPointer;

  [ICarPluginImport("subwoofer")]
  public CarPart mysubwooferPointer;

  [Export]
  public void setStatus(int newStatus)
  {
    Status = newStatus;
  }
}
现在在我的CarSystem类中,我定义了导出,但是默认行为是创建一个静态对象,并将其交给所有导入它的人;我如何才能做到以下几点:

[ExportAsThreadsafe]
public CarPart FrontSpeakers

[ExportAsThreadsafe]
public CarPart RearSpeakers

[ExportAsThreadsafe]
public CarPart Subwoofer

[ExportAsThreadsafe]
public CarPart DashLights

因此,当我创建在单独线程上运行的第二个插件时,我会获得一个到所有插件的实际对象的线程安全连接。

在MEF中提供线程安全的一种方法是在每个线程中执行单独的MEF组合。在该组合中构造的所有内容都是该线程的局部内容。任何跨线程访问都在您的控制之下,您可以使用正常的线程安全技术


我不清楚您是否希望加载多个立体声插件,并将它们提供给/绑定到一个全局CarSystem,或者您只是说在不同的线程中拥有多个CarSystem,彼此独立。您可以通过MEF在线程中使用特定的立体声插件组合CarSystem来实现后者。

以下是我最后要做的(伪代码):

Foreach plugin dynamically loaded
{
    //Via reflection
    Foreach field in the plugin
    {
        See if the field has an attribute attached
        Find the field who's name is the same as it's attribute's name
        {
            Using some lookup method, find the object in the CarSystem
            collection who's name is the same as the attribute name.
            create a concurrencyQueue using proxy object
            call field.SetValue(pluginObject, new Proxy Object) //Reflection call
        }
    }
}


我基本上是说,“该死的,MEF会自动完成这项工作”,然后我自己使用反射和自定义属性完成了这项工作。我使用MEF进行单向消息传递,但对于需要更改CarSystem中对象的插件,我使用了自定义的“MEF”样式。

“线程安全连接到对象”?绝对没有用于线程的金锤,尤其是微软作为MEF的一部分提供的一个足够可靠的金锤。使用
[PartCreationPolicy(CreationPolicy.NonShared)]
将为每个对象提供一个唯一的实例(如果使用正确,“更”线程安全)。这听起来有点粗鲁——但这确实是一个好主意:去努力学习为什么这不起作用,你就会对线程有足够的了解,从而真正使用它。简单回答-
[Import]
对象并一如既往地锁定它们。就像提出一个解决方案,然后建议我了解更多为什么“这个”不起作用一样,我理解使某些线程安全的问题;我想,我的问题并没有完全说明我提出的算法。有一组对象。每个对象都有一个与之关联的并发队列(它已经是线程安全的)。当插件请求访问该对象时,它会得到该对象的一个副本,该副本将消息直接转储到队列中。空闲时,我处理队列中当前的所有请求。提供给插件的对象是/可以在单独的线程中,但是队列和系统中的所有其他对象都在一个线程中运行。以这种方式,我打算避免任何线程冲突。我的问题是:如何创建一个简单的自定义导出提供程序来实现这一点。如果我正确理解您的解释
[PartCreationPolicy(CreationPolicy.NonShared)]
将执行您希望它执行的操作-我从未编写过导出提供程序,因此您可能需要使用此信息更新问题。不幸的是,
[PartCreationPolicy(CreationPolicy.NonShared)]
仅适用于类,不是领域我要说的是:一个拥有一系列对象的系统。所有希望访问CarSystem集合的插件都可以以线程安全的方式访问(因为每个插件可能是一个单独的线程)@BenjaminKiefer MEF exports不会为您这样做。您最好将CarSystem集合设置为新的threadsafe集合(.net 4.0)之一,并导出集合对象本身,或者导出CarSystem包装对象,该对象具有获取内部私有集合周围锁的访问方法。如果枚举内部列表是一项频繁的活动,则后者将很棘手。我倾向于导出一个预烘焙的线程安全集合。@dthrope整个事情的想法是编写插件的人不是我,我不想让他们知道我的对象集合的确切结构是如何构造的。这样,我就可以在不必重建代码的情况下进行重组。我还希望一个普通的街头小孩儿能够相当容易地理解如何为我的系统编写插件。如果你实现CarSystem包装器来导出插件绑定的方法,插件编写者不需要知道CarSystem的结构。包装器是默认MEF绑定和内部线程安全代码之间的桥梁。