プラグイン ハンドラを作成しようとすると、いくつかの問題が発生します。
「AssemblyX」を参照するメインアプリケーション「AppA」があります。
AppA は、「IPlugin」インターフェイスを実装する多数のプラグイン アセンブリも読み込みます。ただし、これらのプラグインは「AssemblyX」を参照することもあり、古いバージョンである場合もあります。
したがって、最初の問題は、Assembly.LoadFrom() を介してプラグインをロードするときに発生した AssemblyX との競合でした。
ここで少し調査した後、新しい AppDomain にプラグインをロードしてみました。これだけでは問題は解決しませんでした。次に、MarshalByRefObject から継承した ProxyDomain クラスを作成しました。まだ喜びはありません。
最後に、プラグイン自体を MarshalByRefObject から継承するようにしました。これにより、より多くの成功が得られましたが、List を ListView にバインドしようとすると、「System.MarshalByRefObject」には「SomeProperty」という名前のプロパティが含まれていないと不平を言いました。
誰かが私のコードに目を向けて、変更が加えられるかどうかを確認してください:
public partial class WebForm1 : System.Web.UI.Page
{
protected void Button1_Click(object sender, EventArgs e)
{
AssemblyX x = new AssemblyX();
x.GetStuff("a", "b");
lstConfig.DataSource = PluginLoader.Load(Path.Combine(PluginLoader.GetPluginFolderPath(), "ExamplePlugins.dll"));
lstConfig.DataBind();
}
}
public class PluginLoader
{
public static List<IPlugin> Load(string file)
{
var plugins = new List<IPlugin>();
ProxyDomain pd = new ProxyDomain();
Assembly ass = pd.GetAssembly(file);
try
{
AppDomainSetup adSetup = new AppDomainSetup();
string fileName = Path.GetFileName(file);
string path = file.Replace(fileName, "");
adSetup.ApplicationBase = path;
AppDomain crmAppDomain = AppDomain.CreateDomain("ProxyDomain", null, adSetup);
foreach (Type t in ass.GetTypes())
{
Type hasInterface = t.GetInterface(typeof(IPlugin).FullName, true);
if (hasInterface != null && !t.IsInterface)
{
IPlugin plugin = (IPlugin)crmAppDomain.CreateInstanceAndUnwrap(ass.FullName, t.FullName);
plugins.Add(plugin);
}
}
}
catch (Exception ex)
{
}
return plugins;
}
public class ProxyDomain : MarshalByRefObject
{
public Assembly GetAssembly(string assemblyPath)
{
try
{
return Assembly.LoadFrom(assemblyPath);
}
catch (Exception ex)
{
throw ex;
}
}
}
public interface IPlugin
{
string SomeProperty { get; set; }
void DoSomething();
}
[Serializable]
public class ExamplePlugin : MarshalByRefObject, IPlugin
{
public string SomeValue
{
get
{
AssemblyX x = new AssemblyX(); // Referencing a previouus version of AssemblyX
return x.GetStuff("c");
}
set
{
}
}
public void DoSomething() { }
}
注: PluginExamples.dll には、複数のプラグイン クラスが含まれている場合があります。