私は将来の開発者がアプリケーション用のプラグインを作成できるwinformsプロジェクトを持っています。 Winformsアプリケーションには、開発者がプラグインの作成時に参照する必要があるすべてのインターフェイスとクラスが含まれています。したがって、私がプラグインを作成するとき、私はメインアプリケーションのdllを参照します。
メインアプリケーションが初期化されるとき、私はすべてのプラグインDLLをロードするための別個のドメインを作成します。私がこれを行うのは、appDomain.unload呼び出しを使って自由にプラグインを削除し、残りのプラグインをリロードすることができるからです。 VS2008でデバッグを開始すると、アプリケーションが初期化され、最初のプラグインがロードされますが、メインアプリケーションのインターフェイスを参照するために使用するプラグインの参照先DLLをロードする必要があるという警告が表示されます。
私の質問は、サブドメインにDLLをロードする前に、メインアプリケーションのインターフェイスを使用してプラグインのインスタンスを参照として使用することができますか?はいの場合、どうすればいいですか?どんな助けもありがとうございます。
これは、app.configファイルにあるプラグインを読み込むアプリケーションのPluginManagerです。私は助けが必要なメソッドとクラスのコンストラクタしか保持していませんでした。 このクラスでは、app.cinfigファイルを読んで、customConfigSectionの内容をcustomConfigコレクションに入れています。 loadAssembliesが呼び出されると、コレクションをループし、コンストラクタで作成されたサブドメインにアセンブリを追加します。アセンブリをプラグインとしてロード
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
この次のクラスは、別々のプロジェクトでは1つのクラスです。私はpluginManagerのLoadAssembliesメソッドをテストするために空のプラグインをスタブしています。 Visual StudioによってこのプロジェクトのbinディレクトリにコピーされたMyApp.Core.dllへの参照を追加します。メインアプリケーションにあるインタフェースを実装するためには、これが必要です。
このクラスは、ゲッタとセッタに加えて空のメソッドです。
///////////////////////////////////////////////////////////
// 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
}
あなたの質問が正確であるかわかりません。 Visual Studioでデバッグするときに問題がありますか?それとも、実際にアプリケーションをコンパイルするのは問題ですか?またはそれを実行する? –
問題は、アプリケーションを実行しています。最初のプラグインが読み込まれると、プラグインがMyApp.Coreをロードしていないことを示すランタイムエラーが発生します。これが失敗するコード行は、MyApp.Coreを参照として使用するアセンブリをロードしています。その参考は、私が構築したモック・プラグイン・プロジェクトで行われます。 – gsirianni