1、本文主要使不适用第三方工具,纯手工的WPF主项目加载另一个WPF的项目,这里我们加载的是*.exe。
2、项目结构如下图。AbstractionLayer用于创建插件的接口。WPFIPluginDemo是主程序。WpfPlugin3是要加载的插件程序。
3、 AbstractionLayer中添加接口IPlugin。接口内容如下。
cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AbstractionLayer
{
public interface IPlugin
{
void Initialize();
}
}
4、WPFIPluginDemo项目中MainWindow.xaml代码如下。
XML
<Window x:Class="WPFIPluginDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPFIPluginDemo"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<Button x:Name="btnSearchPlugins" Content="搜索插件" Click="BtnSearchPlugins_OnClick"/>
<Button x:Name="btnShowPlugin" Content="显示插件" Click="BtnShowPlugin_OnClick" Margin="0,10,0,0"/>
</StackPanel>
</Window>
MainWindow.xaml.cs代码如下。
cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using AbstractionLayer;
using Path = System.IO.Path;
namespace WPFIPluginDemo
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void BtnSearchPlugins_OnClick(object sender, RoutedEventArgs e)
{
LoadPlugins(GetCurrentProgramPath()+"\\Plugins");
}
public static string GetCurrentProgramPath()
{
// 获取当前执行的程序集
var assembly = Assembly.GetEntryAssembly();
// 获取程序集所在的路径
var assemblyLocation = assembly.Location;
// 获取程序集所在的目录
var programPath = Path.GetDirectoryName(assemblyLocation);
return programPath;
}
public List<IPlugin> ListIPlugins = new List<IPlugin>();
public void LoadPlugins(string pluginDirectory)
{
try
{
// 获取所有插件DLL
var pluginDlls = Directory.GetFiles(pluginDirectory, "*.exe", SearchOption.TopDirectoryOnly);
foreach (var dll in pluginDlls)
{
Assembly pluginAssembly = Assembly.LoadFrom(dll);
// 查找实现了IPlugin接口的类型
var pluginTypes = pluginAssembly.GetTypes().Where(t => typeof(IPlugin).IsAssignableFrom(t) && !t.IsInterface);
foreach (var pluginType in pluginTypes)
{
IPlugin plugin = (IPlugin)Activator.CreateInstance(pluginType);
plugin.Initialize();
// 管理插件的代码
ListIPlugins.Add(plugin);
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
private void BtnShowPlugin_OnClick(object sender, RoutedEventArgs e)
{
Type plugin = ListIPlugins[0].GetType();
MethodInfo showInfo = plugin.GetMethod("Show");//得到dll或exe文件的中的方法
showInfo.Invoke(ListIPlugins[0], null);//方法调用
}
}
}
5、WpfPlugin3项目中创建WpfPlugin.cs。代码如下。
cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AbstractionLayer;
namespace WpfPlugin3
{
public class WpfPlugin : IPlugin
{
public MainWindow _MainWindow = null;
public void Initialize()
{
_MainWindow = new MainWindow();
}
public void Show()
{
if (_MainWindow!=null)
{
_MainWindow.ShowDialog();
}
}
}
}
MainWindow.xaml代码如下。
XML
<Window x:Class="WpfPlugin3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfPlugin3"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800" WindowStyle="None">
<Grid>
<Button Content="WpfPlugin3" Width="200" Height="200"></Button>
</Grid>
</Window>
6、在WPFIPluginDemo的Debug目录下创建文件夹Plugins,将WpfPlugin3.exe复制到此文件夹下。如下图。
7、示例代码下载路径。