从 ClassLibrary 加载一个 XAML 文件到 ResourceDictionary

Load a XAML file in a ResourceDictionary from a ClassLibrary

我正在尝试制作一个简单的插件系统,其中的插件在应用程序启动时从 .dll 文件动态加载并显示在 UI。

This Answer 似乎正是我要找的。它使用 MEF 加载插件。我尝试创建一个简单的项目并按照说明进行操作。我的解决方案具有以下结构:

MefTest.SDK -> IPlugin.cs

public interface IPlugin
{
    IPluginViewModel ViewModel { get; }
    ResourceDictionary View { get; }
    string Title { get; }
}

MefTest.SDK -> Engine.cs

public class Engine
{
    [ImportMany]
    private IEnumerable<IPlugin> plugins { get; set; }

    public async Task<ObservableCollection<IPlugin>> GetPlugins()
    {
        try
        {
            var folder = AppDomain.CurrentDomain.BaseDirectory;
            var catalog = new AggregateCatalog();
            //catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
            catalog.Catalogs.Add(new DirectoryCatalog(folder));
            var container = new CompositionContainer(catalog);
            container.ComposeParts(this);

            var result = new ObservableCollection<IPlugin>();

            foreach (var p in plugins)
            {
                result.Add(p);
            }

            return result;
        }
        catch (Exception ex)
        {
            //I get the exception here...
            var t = ex;
            throw;
        }
    }
}

MefTest.Plugin1 -> Plugin1.cs

[Export(typeof(IPlugin))]
public class Plugin1 : IPlugin
{
    private MainViewModel viewModel { get; set; }

    public IPluginViewModel ViewModel
    {
        get { return viewModel; }
    }

    public ResourceDictionary View
    {
        get { return viewDictionary; }
    }

    private ResourceDictionary viewDictionary = new ResourceDictionary();

    public string Title
    {
        get { return "Plugin 1"; }
    }

    [ImportingConstructor]
    public Plugin1()
    {
        //I get the error here. tried both of these, none of them work
        viewDictionary.Source =
        //    new Uri("pack://application:,,,/MefTest.Plugin1;component/views/main.xaml", UriKind.Absolute);
        new Uri("/MefTest.Plugin1;component/views/main.xaml", 
        UriKind.Relative);
    }

    public override string ToString()
    {
        return Title;
    }
}

但是,我收到错误 Could not load file or assembly 'MefTest.Plugin1.dll, Culture=neutral' or one of its dependencies. The system cannot find the file specified.

Main.xaml 文件在 MefTest.Plugin1\Views\Main.xaml 文件夹中。项目的输出类型为 ClassLibrary,xaml 文件的生成操作为 Page.

PS:我尝试直接引用插件并在没有 MEF (Plugins.Add(new Plugin3.Plugin3());) 的情况下添加它,它仍然抛出相同的异常。所以我认为问题不在于解决方案的 MEF 部分。

我该如何解决这个问题?另外,这种方法有更好的选择吗?

我在 xbap 应用程序中这样做...以检索远程 xaml。尝试对您的本地资源做同样的事情

private ResourceDictionary LoadDictionary(string source)
    {
        Stream streamInfo = null;
        ResourceDictionary dictionary = null;

        try
        {
            streamInfo = DistantManager.Instance.GetResource(source);

            if (streamInfo != null)
            {
                Uri baseUri = DistantManager.Instance.GetUri(source);

                dictionary = XamlReader.Load(streamInfo) as ResourceDictionary;

                dictionary.Source = baseUri;
            }
        }
        catch (Exception e)
        {
            BusinessLogger.Manage(e);
            return null;
        }

        return dictionary;
    }

类似于

Uri baseUri = new Uri(Mysource);
                dictionary = XamlReader.Load(XXXX) as ResourceDictionary;
                dictionary.Source = baseUri;

但另一方面我不明白为什么你想要一个 ResourceDictionary 作为你的插件视图...?只需创建插件用户控件 ??