2016-02-18 10 views
0

Я строю модульное приложение с MEF и пытаюсь придумать умные идеи о том, как дескрипторы сохраняют/загружают состояния. В некоторых ситуациях (например, когда пользователь нажимает «сохранить»), моя оболочка должна будет инициировать какое-то действие сохранения/загрузки, которое плагины могут знать, чтобы иметь возможность сохранять и загружать свои собственные состояния.Как выполнять действие, когда MEF создает экземпляр (экспорт) нового объекта?

Есть много возможных способов, конечно, включая события и глобальной шине сообщений, однако моя любимая идея в данный момент на базе двух интерфейсов:

public interface ISaveAndLoadState 
{ 
    void SaveState(XmlWriter writer); 
    void LoadState(XmlReader reader); 
} 

public interface IStateManager 
{ 
    void Register(ISaveAndLoadState item); 

    void Save(Stream stream); 
    void Load(Stream stream); 
} 

Тогда плагинов - их модули, вид модели или что угодно - могли бы сделать следующее:

[Export] 
public class iAmAPluginViewModelOrModule : ISaveAndLoadState 
{ 
     [ImportingConstructor] 
    public iAmAPluginViewModelOrModule(IStateManager m) 
    { 
     m.Register(this); 
    } 

    public void SaveState(XmlWriter writer) { ..... } 
    public void LoadState(XmlReader reader) { ..... } 

} 

Это должно работать достаточно хорошо. Тем не менее, я думаю, было бы еще лучше, если бы классы, реализующие ISaveAndLoadState, не должны были явно вызывать IStateManager.Register(), а скорее, когда MEF создает экземпляр класса, реализующего ISaveAndLoadState, он автоматически регистрирует его с помощью IStateManager.

Так в основном, я должен был бы «событие» запускающего всякий раз, когда MEF конкретизирует любой новый объект, а затем сделать что-то вроде

public void OnMefHasCreatedInstance(object instance) 
{ 
    var _inst = instance as ISaveAndLoadState; 

if(_inst != null) 
    Container.GetExportedValue<IStateManager>().Register(_inst); 
} 

Возможно ли это вообще? Есть ли способ послушать/быть информированным, когда MEF создал новый экземпляр?

ответ

0

Это не совсем ответ на ваш вопрос, но это, возможно, другое решение для вас.

При экспорте каждый класс с интерфейсом ISaveAndLoadState, то вы можете использовать ImportMany в пределах вашего StateManager

[Export(typeof(ISaveAndLoadState))] 
public class iAmAPluginViewModelOrModule : ISaveAndLoadState 

public class StateManager : IStateManager 
{ 
    [ImportMany(typeof(ISaveAndLoadState))] 
    private List<ISaveAndLoadState> _saveAndLoadStates; 
} 

Тогда _saveAndLoadStates должны быть заполнены все объекты, и вы можете просто цикл через них в StateManagerLoad и Save методов.

+0

Спасибо Том. Не все классы, использующие это, будут составлены, но что более важно - я предпочел бы, чтобы экспорт был создан при необходимости потребителями, а не сразу при импорте в диспетчер состояний (и если я импортирую их как Lazy , я может зарегистрировать их слишком поздно). Теперь я пошел с использованием InterceptingCatalog из MefContrib и зарегистрировал IExportedValueInterceptor для регистрации в моем диспетчере состояний после создания экземпляра; почти кажется немного переборщиком, но пока это работает довольно красиво. – Bogey