废话少说,这个类我封装好了。
首先看下约定:
namespace PluginContract
{
public interface IPlugin
{
string Name { get; set; }
void SayHello();
}
public interface IPluginMark
{
string Mark { get; }
}
}
//IPluginMark用来标识MetaData属性
自动加载插件类:
public class PlugerBase<T>
{
public T GetClass(string className)
{
if (Names.Contains(className))
{
var plug = DoPluginList.Where(i => i.Metadata.Mark == className).Select(p => p.Value).FirstOrDefault();
return (T)plug;
}
else
{
return default(T);
}
}
public string[] Names
{
get
{
List<string> name = new List<string>();
foreach (var item in DoPluginList)
{
name.Add(item.Metadata.Mark);
}
return name.ToArray();
}
}
/// <summary>
/// 插件列表
/// </summary>
[ImportMany]
private List<Lazy<T, IPluginMark>> DoPluginList = new List<Lazy<T, IPluginMark>>();
public PlugerBase(string subFolderName="Plug")
{
Directory.CreateDirectory(Environment.CurrentDirectory + "\\"+ subFolderName);
var catelog = new AggregateCatalog();
AssemblyCatalog assemblyCataLog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
catelog.Catalogs.Add(new DirectoryCatalog(subFolderName));
var container = new CompositionContainer(catelog);
container.ComposeParts(this);
}
}
插件端:
第一个:
namespace MEF_Demo//第一个插件实现的插件需要被调用应用的命名空间一致,切记
{
[ExportMetadata("Mark", "2")]//Mark需要和接口名称同步IPluginMark.后面的2便是GetClass(string className)的className
[Export(typeof(IPlugin))]
public class PluginFirst : IPlugin
{
public string Name { get; set; } = "张三";
public void SayHello()
{
MessageBox.Show($"你好啊{Name}");
}
}
}
第二个:
namespace MEF_Demo
{
[ExportMetadata("Mark","1")]
[Export(typeof(IPlugin))]
public class PluginSecod : IPlugin
{
public string Name { get; set; } = "李四";
public void SayHello()
{
MessageBox.Show($"你好啊{Name}");
}
}
}
最后调用时非常简单:
public MainWindow()
{
InitializeComponent();
PlugerBase<IPlugin> plug = new PlugerBase<IPlugin>();//编译好的插件需要放置在Plug文件夹内
var d= plug.GetClass("1");//通过名称直接反射出对应的类
d.SayHello();
}