从 ClassLibrary 加载一个 XAML 文件到 ResourceDictionary
Load a XAML file in a ResourceDictionary from a ClassLibrary
我正在尝试制作一个简单的插件系统,其中的插件在应用程序启动时从 .dll 文件动态加载并显示在 UI。
This Answer 似乎正是我要找的。它使用 MEF 加载插件。我尝试创建一个简单的项目并按照说明进行操作。我的解决方案具有以下结构:
- MeftTest(包含主要内容 MefTest.exe,仅引用
MefTest.SDK
而不是插件)
- MefTest.SDK(包含
IPlugin.cs
和 IPluginViewModel.cs
以及从应用程序目录加载插件的 Engine.cs)
- MefTest.Plugin1(包含第一个插件,引用
MefTest.SDK
)
- MefTest.Plugin2(包含第二个插件,引用
MefTest.SDK
)
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 作为你的插件视图...?只需创建插件用户控件 ??
我正在尝试制作一个简单的插件系统,其中的插件在应用程序启动时从 .dll 文件动态加载并显示在 UI。
This Answer 似乎正是我要找的。它使用 MEF 加载插件。我尝试创建一个简单的项目并按照说明进行操作。我的解决方案具有以下结构:
- MeftTest(包含主要内容 MefTest.exe,仅引用
MefTest.SDK
而不是插件) - MefTest.SDK(包含
IPlugin.cs
和IPluginViewModel.cs
以及从应用程序目录加载插件的 Engine.cs) - MefTest.Plugin1(包含第一个插件,引用
MefTest.SDK
) - MefTest.Plugin2(包含第二个插件,引用
MefTest.SDK
)
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 作为你的插件视图...?只需创建插件用户控件 ??