2012-03-01 2 views
3

Я узнал, что MEF ограничен для приложений в стиле метро. Больше нет контейнера, так как я могу получить определенные экспортированные значения, например ILogger logger = container.GetExportedValues<ILogger>();? Доступен ли какой-либо учебник, охватывающий версию MEF в метро?Как получить экспортированные значения (MEF) в приложениях стиля метро

Спасибо за помощь, Eny

+0

вы нашли решение? Я закончил с ExportFactory и SatisfyImportsOnce, но я не удовлетворен этим, мне нужно просто GetExportedValues ​​ –

+0

Я общаюсь с одним из ребят, разрабатывающих MEF для приложений в стиле метро. Он сказал мне, что SatisfyImportsOnce в настоящее время является единственным способом создания элементов. Он спросил меня, какие конкретные сценарии я имею в виду, которые не поддерживаются SatisfyImportOnce: http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/6aff302d-867a-4921-86ae-b8088c47560f Я нашел крошечную альтернативу MEF на данный момент: http://metroioc.codeplex.com/ Надеюсь, он также может вам помочь. – Enyra

+0

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

ответ

1

Как я уже писал в комментариях, я не очень нравится такой подход, но это лучшее, что я до этого момента:

public class CompositionContainer 
{ 
    private readonly CompositionService _service; 

    public CompositionContainer(CompositionService service) 
    { 
     _service = service; 
    } 

    public T GetExportedValue<T>() 
    { 
     var factoryProvider = new FactoryProvider<T>(); 
     _service.SatisfyImportsOnce(factoryProvider); 
     return factoryProvider.Factory.CreateExport().Value; 
    } 

    private class FactoryProvider<T> 
    { 
     [Import] 
     public ExportFactory<T> Factory; 
    } 
} 

и простой потребительной случае может быть это один:

class Program 
{ 
    static void Main() 
    { 
     var catalog = new ApplicationCatalog(); 
     var container = new CompositionContainer(catalog.CreateCompositionService()); 
     for (int i = 0; i < 5; i++) 
     { 
      var dude = container.GetExportedValue<IDude>(); 
      Console.WriteLine(dude.Say()); 
     } 
    } 
    public interface IDude 
    { 
     string Say(); 
    } 

    [Export(typeof(IDude))] 
    public class Eminem : IDude 
    { 
     private static int _instanceNo; 
     private readonly string _phrase; 

     public Eminem() 
     { 
      _instanceNo++; 
      _phrase = string.Join(" ", Enumerable.Range(0, _instanceNo) 
       .Select(_ => "yo!")); 
     } 

     public string Say() 
     { 
      return _phrase; 
     } 
    } 
} 

Я не беспокоюсь о производительности на данный момент, но я думаю, я буду добавлять кэширование заводских поставщиков или заводов позже

+0

Это не плохой подход! Просто питти, что мы должны написать такой код себе :(Спасибо, чувак. – Enyra

2

Я предполагаю, что вы обнаружили System.CompononentModel.Composition и System.CompononentModel.Composition.Hosting пространств имен.

Позвольте мне привести простой пример здесь (и посмотреть, нет ли у вас чего-либо).

Прежде всего, вам нужен компонент для введения:

public interface IMefTest 
{ 
    string Message {get;} 
} 

[Export(typeof(IMefTest))] 
public class MefTest: IMefTest 
{ 
    public string Message {get { return "Hello World"; }} 
} 

Далее вам нужно настроить CompositionService (это похоже на контейнер, но не точно). Мы хотим установить это где-то, с которым обычно можно поговорить, так как это будет то, где вы вызываете, чтобы удовлетворить импорт (подробнее об этом в фрагменте кода после этого).

Я застрял в этом App.xaml.cs в моем примере проекта:

static System.ComponentModel.Composition.ICompositionService _compositionService = null; 
public static System.ComponentModel.Composition.ICompositionService CompositionService 
{ 
    get 
    { 
     if (_compositionService == null) 
      ((App)App.Current).loadCompositionService(); 
     return _compositionService; 
    } 
} 

private void loadCompositionService() 
{ 
    // Create a catalog where MEF will search for exported parts to plugin 
    var catalog = new System.ComponentModel.Composition.Hosting.AssemblyCatalog(GetType().GetTypeInfo().Assembly); 
    _compositionService = catalog.CreateCompositionService(); 
} 

Просто мало информации об этом. Мы создали каталог сборки, что означает, что MEF будет допрашивать только эту Ассамблею, ища типы, которые экспортируются. Существуют и другие типы каталогов, и я считаю, что вы должны объединить 2 или более каталогов.

Хорошо, на моей странице (BTW, я построил это в примере C# HelloWorld из документов Getting Started on MSDN).

Чтобы получить экземпляр одной из частей каталога, вам просто нужно добавить свойство к классу, который вы хотите получить, и добавить атрибут импорта (есть также способы указать аргументы в вашем конструкторе, но Я пытаюсь остаться простым)

[Import] 
public IMefTest Tester { get; set; } 

в этом примере, вам нужно вызвать метод SatisfyImportsOnce на службу композиции, по этому классу. Я сделал это в конструкторе, и я сделал это так:

if(App.CompositionService != null) 
    App.CompositionService.SatisfyImportsOnce(this); 

(Проверка, чтобы убедиться, что сервис существует, это излишество с моей стороны .. он должен существовать). После этого шага вы можете использовать свойство Tester.Message в своем классе. В MEF есть намного больше вариантов. Я надеюсь, что это поможет вам (и если это вы отметите меня как ответ, поскольку я потратил драгоценное время на выставление счетов клиентам, чтобы сделать это за вас)

Кроме того, я знаю, что вы хотели просто вызвать контейнер и дать ему вы возвращаете экземпляр некоторого типа. Это можно сделать с другими формами MEF, поэтому я предполагаю, что это можно сделать с помощью WinRT, но я честно не уверен в это время).

+0

Здравствуйте, DevTheo, это я уже понял, к сожалению, это не совсем то, что я ищу. Контейнер позволил получить конкретную экспортную стоимость без удовлетворения импорта: container.GetExportedValue (); Я ищу эквивалентную функцию на Metro MEF. – Enyra

+0

Извините, я не прибил его для вас ... Я не мог найти то, что вы хотели (и, как я сказал, нужно было вернуться к работе с клиентами ). Если у меня будет шанс, я посмотрю немного дальше .. У меня есть другая идея, но мне нужно поэкспериментировать с чем-то, прежде чем я скажу, что у меня есть это. – DevTheo

+0

Я не ожидаю, что вы прибиваете его для меня;) У меня уже есть идея, как я могу это сделать, но я еще не хватает времени^^ Но я не думаю, что это можно сделать без какого-либо специального кода. – Enyra

Смежные вопросы