C # MEF: потокобезопасный экспорт - PullRequest
2 голосов
/ 09 ноября 2011

Предположим, у меня есть класс 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 я определяю экспорт, однако поведение по умолчанию - создать 1 статический объект и передать его всем импортирующим его; Как бы я мог сделать следующее:

[ExportAsThreadsafe]
public CarPart FrontSpeakers

[ExportAsThreadsafe]
public CarPart RearSpeakers

[ExportAsThreadsafe]
public CarPart Subwoofer

[ExportAsThreadsafe]
public CarPart DashLights

так что, когда я создаю второй плагин, работающий в отдельном потоке, я получаю потокобезопасное соединение с реальным объектом для всех плагинов?

Ответы [ 2 ]

1 голос
/ 09 ноября 2011

Одним из способов обеспечения безопасности потока в MEF является выполнение отдельной независимой композиции MEF в каждом потоке. Все, что построено в этой композиции, является локальным для этого потока. Любой доступ между потоками находится под вашим контролем, и вы можете использовать обычные методы обеспечения безопасности потоков.

Мне неясно, хотите ли вы загрузить несколько стереоплагинов и сделать их доступными для одной глобальной CarSystem или привязанными к ней, или вы просто говорите о наличии нескольких CarSystems в разных потоках, независимых друг от друга. Вы можете сделать это путем создания MEF CarSystem с определенным стерео плагином внутри потока.

0 голосов
/ 10 ноября 2011

Вот что я в итоге сделал (в псевдокоде):

</p> <pre><code>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 делает это автоматически» и сделал это сам, используя Reflection и пользовательские атрибуты. Я использовал MEF для обмена сообщениями в одном направлении, но для плагинов, которые должны были изменять объекты в CarSystem, я использовал свой собственный стиль «MEF».

...