Используйте приложение WPF для запуска нескольких различных приложений с использованием MEF - PullRequest
4 голосов
/ 01 февраля 2011

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

Я очень плохо знаком с MEF, поэтому я написал тестовое приложение и попытался заставить MEF работать. Тестовое приложение определяет очень простой интерфейс ITool. Мне удалось импортировать несколько классов из библиотек классов без затруднений, однако я не смог импортировать другое приложение WPF. Это возможно с MEF?

Мое основное приложение WPF создает экземпляр ToolContainer, который создает и компонует части.

class ToolContainer
{
    [ImportMany(typeof(ITool))]
    IEnumerable<Lazy<ITool>> _tools;

    private CompositionContainer _container;

    public ToolContainer()
    {
        AggregateCatalog catalog = new AggregateCatalog();
        catalog.Catalogs.Add(new DirectoryCatalog(
            "C:\\Application Development\\Tool Center\\Tool Extensions"));

        _container = new CompositionContainer(catalog);

        try
        {
            _container.ComposeParts(this);
        }
        catch (CompositionException compositionException)
        {
            //TODO: show error dialog
        }
    }

}

Вот интерфейс

public interface ITool
{
    String ToolName { get; }
    void OpenTool();
}

Я создал несколько классов, которые наследуются от ITool, и экспорт прекрасно работает. Один пример здесь.

[Export(typeof(ITool))]
public class Class1 : ITool
{
    public String ToolName
    {
        get { return "....."; }
    }

    public void OpenTool()
    {
        //open the tool
    }
}

Теперь я хочу импортировать все приложение WPF, которое наследует интерфейс ITool. Идея заключается в том, что внешние пользователи могут создавать свои собственные приложения WPF, которые можно будет запускать из основного приложения WPF. В будущем интерфейс ITool будет намного более продвинутым, но я пытаюсь сделать основы прямо сейчас. Я создал новый тестовый проект WPF и изменил файл App.xaml.cs так, чтобы он был следующим:

[Export(typeof(ITool))]
public partial class App : Application, ITool
{
    public String ToolName
    {
        get { return "Tool Sample"; }
    }

    public void OpenTool()
    {
       //open the tool
    }
}

Когда я делаю это, _tools не содержит моего нового приложения WPF, но содержит Class1. Есть идеи, что я делаю не так? Есть ли лучший подход? Любая помощь будет принята с благодарностью.

1 Ответ

7 голосов
/ 01 февраля 2011

По умолчанию, Конструктор DirectoryCatalog ищет только типы в файлах *.dll в каталоге.Вы можете сделать это «работой», добавив второй каталог для поиска типов в исполняемых файлах .NET, например:

AggregateCatalog catalog = new AggregateCatalog();
catalog.Catalogs.Add(new DirectoryCatalog(
        "C:\\Application Development\\Tool Center\\Tool Extensions"));
catalog.Catalogs.Add(new DirectoryCatalog(
        "C:\\Application Development\\Tool Center\\Tool Extensions", "*.exe")); 

При этом я бы рекомендовал против этого.Вместо того, чтобы ваши пользователи экспортировали приложения, я бы порекомендовал им экспортировать UserControl, который реализует ITool.Это будет вести себя гораздо более ожидаемым образом, поскольку «Приложение» действительно спроектировано и должно запускаться как свой собственный Процесс, а не быть составленным внутри одного родительского процесса.

...