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