C# 将程序集加载为插件
我有一个winforms项目,它允许未来的开发人员为应用程序创建插件。Winforms应用程序包含开发人员在创建插件时需要引用的所有接口和类。因此,当我创建插件时,我引用了主应用程序的DLL。C# 将程序集加载为插件,c#,.net,winforms,assemblies,C#,.net,Winforms,Assemblies,我有一个winforms项目,它允许未来的开发人员为应用程序创建插件。Winforms应用程序包含开发人员在创建插件时需要引用的所有接口和类。因此,当我创建插件时,我引用了主应用程序的DLL。 当主应用程序初始化时,我创建一个单独的域来加载所有插件dll。我这样做的原因是,我可以使用appDomain.unload调用随意删除插件,然后重新加载其余的插件。 当我在VS2008中启动调试时,我的应用程序初始化,它加载第一个插件,但我得到一个警告,我需要加载插件的引用DLL,我使用它引用主应用程序
当主应用程序初始化时,我创建一个单独的域来加载所有插件dll。我这样做的原因是,我可以使用appDomain.unload调用随意删除插件,然后重新加载其余的插件。 当我在VS2008中启动调试时,我的应用程序初始化,它加载第一个插件,但我得到一个警告,我需要加载插件的引用DLL,我使用它引用主应用程序的接口。
现在我的问题是,在将DLL加载到子域之前,我是否可以使用主应用程序的接口来创建它们的实例,供插件用作参考?如果是,我怎么做?感谢您的帮助。
这是我的应用程序的PluginManager,它加载app.config文件中的插件。我只保留了需要帮助的方法和类的构造函数。 在本课程中,我正在阅读app.cinfig文件,并将customConfigSection的内容放入customConfig集合中。调用LoadAssembly时,我将循环集合并将程序集添加到构造函数中创建的子域中
using System;
using MyApp.Data;
using MyApp.Interfaces;
using MyApp.Variables;
using System.Reflection;
namespace MyApp.Core
{
/// <summary>
/// This object helps the application manage its scalable and extended components
/// called plugins.
/// </summary>
public class PlugInManager
{
public PlugInManager()
{
//appDomain setup
pluginDomainSetup = new AppDomainSetup();
pluginDomainSetup.ApplicationBase = pluginDomainLocation;
pluginDomainSetup.DisallowCodeDownload = true;
string pluginApplicationName = string.Format(MAOIE.Variables.Constants.PLUGIN_APPLICATION_NAME);
//appDomain creation
pluginDomain = AppDomain.CreateDomain(pluginApplicationName, null, pluginDomainSetup);
//Loads the values located in the config file
LoadPluginConfiguration();
//Load any existing plugins in the directories
LoadAssemblies();
}
private void LoadAssemblies()
{
//I"m thinking I should add this the referenced libraries to the subdomain here.
//AppDomain.Unload(this.pluginDomain);
string reference = GetReferencePath();
reference += Variables.Constants.MAOIE_CORE_DLL;
//Iterate through the items found in the app.config file.
foreach (PluginSetting item in this.PluginConfigSettings.PluginItems)
{
string file = GetPluginPath();
file += item.PluginFileName;
switch (item.PluginType)
{
case Constants.PluginType.pluginTypeA:
pluginDomain.CreateInstanceFrom(file, item.PluginAssemblyType);
IPluginTypeA ia = (IPluginTypeA)Activator.CreateInstance(pluginDomain, item.PluginFileName, item.PluginAssemblyType);
Plugable<IPluginTypeA> pia = new Plugable<IPluginTypeA>();
pia.ConcreteClass = ia;
pia.Core = false;
//collection used throughout the application
this.aerodynamicAnalyzers.Add(pia);
return;
case Constants.PluginType.pluginTypeB:
pluginDomain.CreateInstanceFrom(file, item.PluginAssemblyType);
IPluginTypeB ib = (IPluginTypeB)Activator.CreateInstance(pluginDomain, item.PluginFileName, item.PluginAssemblyType);
Plugable<IPluginTypeB> pib = new Plugable<IPluginTypeB>();
piB.ConcreteClass = ib;
pim.Core = false;
//collection used throughout the application
this.missionAnalyzers.Add(pib);
return;
case Constants.PluginType.pluginTypeC:
pluginDomain.CreateInstanceFrom(file, item.PluginAssemblyType);
IPluginTypeC ic = (IPluginTypeC)Activator.CreateInstance(pluginDomain, item.PluginFileName, item.PluginAssemblyType);
Plugable<IPluginTypeC> pic = new Plugable<IPluginTypeC>();
pic.ConcreteClass = ic;
pic.Core = false;
//collection used throughout the application
this.pluginTypeCs.Add(pio);
return;
case Constants.PluginType.pluginTypeD:
pluginDomain.CreateInstanceFrom(file, item.PluginAssemblyType);
IPluginTypeD id = (IPluginTypeD)Activator.CreateInstance(pluginDomain, item.PluginFileName, item.PluginAssemblyType);
Plugable<IPluginTypeD> piw = new Plugable<IPluginTypeD>();
pid.ConcreteClass = id;
pid.Core = false;
//collection used throughout the application
this.pluginTypeDs.Add(pid);
return;
}
}
}
}
//end PlugInManager
}
//end namespace MyApp.Core
使用系统;
使用MyApp.Data;
使用MyApp.Interfaces;
使用MyApp.Variables;
运用系统反思;
名称空间MyApp.Core
{
///
///此对象帮助应用程序管理其可扩展组件
///叫做插件。
///
公共类插件管理器
{
公共插件管理器()
{
//appDomain设置
pluginDomainSetup=新建AppDomainSetup();
pluginDomainSetup.ApplicationBase=pluginDomainLocation;
pluginDomainSetup.DisallowCodeDownload=true;
string pluginApplicationName=string.Format(MAOIE.Variables.Constants.PLUGIN\u APPLICATION\u NAME);
//appDomain创建
pluginDomain=AppDomain.CreateDomain(pluginApplicationName,null,pluginDomainSetup);
//加载配置文件中的值
LoadPluginConfiguration();
//加载目录中的任何现有插件
加载程序集();
}
私有void加载程序集()
{
//我想我应该把这个引用库添加到这里的子域中。
//AppDomain.Unload(this.pluginDomain);
字符串引用=GetReferencePath();
reference+=Variables.Constants.MAOIE_CORE_DLL;
//遍历app.config文件中的项目。
foreach(此.pluginFigSettings.PluginItems中的插件安装项)
{
字符串文件=GetPluginPath();
文件+=item.pluginlineName;
开关(项目.插件类型)
{
case常量.PluginType.pluginTypeA:
pluginDomain.CreateInstanceFrom(文件,item.PluginAssemblyType);
IPluginTypeA ia=(IPluginTypeA)Activator.CreateInstance(pluginDomain,item.PluginFileName,item.PluginAssemblyType);
可插拔pia=新的可插拔();
pia.ConcreteClass=ia;
pia.Core=false;
//在整个应用程序中使用的集合
本章。空气动力学分析仪。添加(pia);
返回;
case常量.PluginType.pluginTypeB:
pluginDomain.CreateInstanceFrom(文件,item.PluginAssemblyType);
IPluginTypeB ib=(IPluginTypeB)Activator.CreateInstance(pluginDomain,item.PluginFileName,item.PluginAssemblyType);
可插拔pib=新的可插拔();
piB.ConcreteClass=ib;
pim.Core=false;
//在整个应用程序中使用的集合
这个.任务分析器.Add(pib);
返回;
case常量.PluginType.pluginTypeC:
pluginDomain.CreateInstanceFrom(文件,item.PluginAssemblyType);
IPluginTypeC ic=(IPluginTypeC)Activator.CreateInstance(pluginDomain,item.PluginFileName,item.PluginAssemblyType);
可插拔pic=新的可插拔();
pic.ConcreteClass=ic;
pic.Core=false;
//在整个应用程序中使用的集合
this.pluginTypeCs.Add(pio);
返回;
case常量.PluginType.pluginTypeD:
pluginDomain.CreateInstanceFrom(文件,item.PluginAssemblyType);
IPluginTypeD id=(IPluginTypeD)Activator.CreateInstance(pluginDomain,item.PluginFileName,item.PluginAssemblyType);
可插拔piw=新的可插拔();
pid.ConcreteClass=id;
pid.Core=false;
//在整个应用程序中使用的集合
this.pluginTypeDs.Add(pid);
返回;
}
}
}
}
//端插件管理器
}
//结束名称空间MyApp.Core
下一个类是单独项目中的单个类。我正在存根一个空插件以测试我的pluginManager的LoadAssemblys方法。我添加了对MyApp.Core.dll的引用,该引用由visual studio复制到此项目的bin目录中。我需要它来实现在主应用程序中找到的接口
这个类只是getter和setter加上一个空方法
///////////////////////////////////////////////////////////
// testPluginA.cs
// used as an empty class to test the import of plugins into the main application.
///////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Text;
using MyApp.Core;
namespace testPluginA
{
public class testPluginA : MyApp.Interfaces.IPluginTypeA
{
public testPluginA()
{
}
private string name = "testPluginA";
private string desc = "Test Plugin A 1";
/// <summary>
/// The description of the plugin.
/// </summary>
public string Description { get{return this.desc;} }
/// <summary>
/// The display name of the plugin.
/// </summary>
public string FriendlyName { get{return this.name;} }
/// <summary>
///
/// </summary>
/// <param name="mp"></param>
public void Optimize(MyApp.Data.Car car)
{
//does nothing
}
///////////////////////////////////////////////////////////
//testPluginA.cs
//用作空类,用于测试插件导入主应用程序